Add docstrings for the ltmpl commands in LoraxTemplateRunner
This commit is contained in:
parent
be4d8160b2
commit
473f01c696
@ -153,16 +153,42 @@ class LoraxTemplateRunner(object):
|
|||||||
logger.error(str(e))
|
logger.error(str(e))
|
||||||
|
|
||||||
def install(self, srcglob, dest):
|
def install(self, srcglob, dest):
|
||||||
|
'''
|
||||||
|
install SRC DEST
|
||||||
|
Copy the given file (or files, if a glob is used) from the input
|
||||||
|
tree to the given destination in the output tree.
|
||||||
|
The path to DEST must exist in the output tree.
|
||||||
|
If DEST is a directory, SRC will be copied into that directory.
|
||||||
|
If DEST doesn't exist, SRC will be copied to a file with that name,
|
||||||
|
assuming the rest of the path exists.
|
||||||
|
This is pretty much like how the 'cp' command works.
|
||||||
|
Examples:
|
||||||
|
install usr/share/myconfig/grub.conf /boot
|
||||||
|
install /usr/share/myconfig/grub.conf.in /boot/grub.conf
|
||||||
|
'''
|
||||||
for src in rglob(self._in(srcglob), fatal=True):
|
for src in rglob(self._in(srcglob), fatal=True):
|
||||||
cpfile(src, self._out(dest))
|
cpfile(src, self._out(dest))
|
||||||
|
|
||||||
def mkdir(self, *dirs):
|
def mkdir(self, *dirs):
|
||||||
|
'''
|
||||||
|
mkdir DIR [DIR ...]
|
||||||
|
Create the named DIR(s). Will create leading directories as needed.
|
||||||
|
Example:
|
||||||
|
mkdir /images
|
||||||
|
'''
|
||||||
for d in dirs:
|
for d in dirs:
|
||||||
d = self._out(d)
|
d = self._out(d)
|
||||||
if not isdir(d):
|
if not isdir(d):
|
||||||
os.makedirs(d)
|
os.makedirs(d)
|
||||||
|
|
||||||
def replace(self, pat, repl, *fileglobs):
|
def replace(self, pat, repl, *fileglobs):
|
||||||
|
'''
|
||||||
|
replace PATTERN REPLACEMENT FILEGLOB [FILEGLOB ...]
|
||||||
|
Find-and-replace the given PATTERN (Python-style regex) with the given
|
||||||
|
REPLACEMENT string for each of the files listed.
|
||||||
|
Example:
|
||||||
|
replace @VERSION@ ${product.version} /boot/grub.conf /boot/isolinux.cfg
|
||||||
|
'''
|
||||||
match = False
|
match = False
|
||||||
for g in fileglobs:
|
for g in fileglobs:
|
||||||
for f in rglob(self._out(g)):
|
for f in rglob(self._out(g)):
|
||||||
@ -172,56 +198,130 @@ class LoraxTemplateRunner(object):
|
|||||||
raise IOError, "no files matched %s" % " ".join(fileglobs)
|
raise IOError, "no files matched %s" % " ".join(fileglobs)
|
||||||
|
|
||||||
def append(self, filename, data):
|
def append(self, filename, data):
|
||||||
|
'''
|
||||||
|
append FILE STRING
|
||||||
|
Append STRING (followed by a newline character) to FILE.
|
||||||
|
Python character escape sequences ('\n', '\t', etc.) will be
|
||||||
|
converted to the appropriate characters.
|
||||||
|
Examples:
|
||||||
|
append /etc/depmod.d/dd.conf "search updates built-in"
|
||||||
|
append /etc/resolv.conf ""
|
||||||
|
'''
|
||||||
with open(self._out(filename), "a") as fobj:
|
with open(self._out(filename), "a") as fobj:
|
||||||
fobj.write(data.decode('string_escape')+"\n")
|
fobj.write(data.decode('string_escape')+"\n")
|
||||||
|
|
||||||
def treeinfo(self, section, key, *valuetoks):
|
def treeinfo(self, section, key, *valuetoks):
|
||||||
|
'''
|
||||||
|
treeinfo SECTION KEY ARG [ARG ...]
|
||||||
|
Add an item to the treeinfo data store.
|
||||||
|
The given SECTION will have a new item added where
|
||||||
|
KEY = ARG ARG ...
|
||||||
|
Example:
|
||||||
|
treeinfo images-${kernel.arch} boot.iso images/boot.iso
|
||||||
|
'''
|
||||||
if section not in self.results.treeinfo:
|
if section not in self.results.treeinfo:
|
||||||
self.results.treeinfo[section] = dict()
|
self.results.treeinfo[section] = dict()
|
||||||
self.results.treeinfo[section][key] = " ".join(valuetoks)
|
self.results.treeinfo[section][key] = " ".join(valuetoks)
|
||||||
|
|
||||||
def installkernel(self, section, src, dest):
|
def installkernel(self, section, src, dest):
|
||||||
|
'''
|
||||||
|
installkernel SECTION SRC DEST
|
||||||
|
Install the kernel from SRC in the input tree to DEST in the output
|
||||||
|
tree, and then add an item to the treeinfo data store, in the named
|
||||||
|
SECTION, where "kernel" = DEST.
|
||||||
|
|
||||||
|
Equivalent to:
|
||||||
|
install SRC DEST
|
||||||
|
treeinfo SECTION kernel DEST
|
||||||
|
'''
|
||||||
self.install(src, dest)
|
self.install(src, dest)
|
||||||
self.treeinfo(section, "kernel", dest)
|
self.treeinfo(section, "kernel", dest)
|
||||||
|
|
||||||
def installinitrd(self, section, src, dest):
|
def installinitrd(self, section, src, dest):
|
||||||
|
'''
|
||||||
|
installinitrd SECTION SRC DEST
|
||||||
|
Same as installkernel, but for "initrd".
|
||||||
|
'''
|
||||||
self.install(src, dest)
|
self.install(src, dest)
|
||||||
self.treeinfo(section, "initrd", dest)
|
self.treeinfo(section, "initrd", dest)
|
||||||
|
|
||||||
def hardlink(self, src, dest):
|
def hardlink(self, src, dest):
|
||||||
|
'''
|
||||||
|
hardlink SRC DEST
|
||||||
|
Create a hardlink at DEST which is linked to SRC.
|
||||||
|
'''
|
||||||
if isdir(self._out(dest)):
|
if isdir(self._out(dest)):
|
||||||
dest = joinpaths(dest, basename(src))
|
dest = joinpaths(dest, basename(src))
|
||||||
os.link(self._out(src), self._out(dest))
|
os.link(self._out(src), self._out(dest))
|
||||||
|
|
||||||
def symlink(self, target, dest):
|
def symlink(self, target, dest):
|
||||||
|
'''
|
||||||
|
symlink SRC DEST
|
||||||
|
Create a symlink at DEST which points to SRC.
|
||||||
|
'''
|
||||||
if rexists(self._out(dest)):
|
if rexists(self._out(dest)):
|
||||||
self.remove(dest)
|
self.remove(dest)
|
||||||
os.symlink(target, self._out(dest))
|
os.symlink(target, self._out(dest))
|
||||||
|
|
||||||
def copy(self, src, dest):
|
def copy(self, src, dest):
|
||||||
|
'''
|
||||||
|
copy SRC DEST
|
||||||
|
Copy SRC to DEST.
|
||||||
|
If DEST is a directory, SRC will be copied inside it.
|
||||||
|
If DEST doesn't exist, SRC will be copied to a file with
|
||||||
|
that name, if the path leading to it exists.
|
||||||
|
'''
|
||||||
cpfile(self._out(src), self._out(dest))
|
cpfile(self._out(src), self._out(dest))
|
||||||
|
|
||||||
def copyif(self, src, dest):
|
def copyif(self, src, dest):
|
||||||
|
'''
|
||||||
|
copyif SRC DEST
|
||||||
|
Copy SRC to DEST, but only if SRC exists.
|
||||||
|
'''
|
||||||
if rexists(self._out(src)):
|
if rexists(self._out(src)):
|
||||||
self.copy(src, dest)
|
self.copy(src, dest)
|
||||||
|
|
||||||
def move(self, src, dest):
|
def move(self, src, dest):
|
||||||
|
'''
|
||||||
|
move SRC DEST
|
||||||
|
Move SRC to DEST.
|
||||||
|
'''
|
||||||
mvfile(self._out(src), self._out(dest))
|
mvfile(self._out(src), self._out(dest))
|
||||||
|
|
||||||
def moveif(self, src, dest):
|
def moveif(self, src, dest):
|
||||||
|
'''
|
||||||
|
moveif SRC DEST
|
||||||
|
Move SRC to DEST, but only if SRC exists.
|
||||||
|
'''
|
||||||
if rexists(self._out(src)):
|
if rexists(self._out(src)):
|
||||||
self.move(src, dest)
|
self.move(src, dest)
|
||||||
|
|
||||||
def remove(self, *fileglobs):
|
def remove(self, *fileglobs):
|
||||||
|
'''
|
||||||
|
remove FILEGLOB [FILEGLOB ...]
|
||||||
|
Remove all the named files or directories.
|
||||||
|
'''
|
||||||
for g in fileglobs:
|
for g in fileglobs:
|
||||||
for f in rglob(self._out(g)):
|
for f in rglob(self._out(g)):
|
||||||
remove(f)
|
remove(f)
|
||||||
|
|
||||||
def chmod(self, fileglob, mode):
|
def chmod(self, fileglob, mode):
|
||||||
|
'''
|
||||||
|
chmod FILEGLOB OCTALMODE
|
||||||
|
Change the mode of all the files matching FILEGLOB to OCTALMODE.
|
||||||
|
'''
|
||||||
for f in rglob(self._out(fileglob), fatal=True):
|
for f in rglob(self._out(fileglob), fatal=True):
|
||||||
os.chmod(f, int(mode,8))
|
os.chmod(f, int(mode,8))
|
||||||
|
|
||||||
|
# TODO: do we need a new command for gsettings?
|
||||||
def gconfset(self, path, keytype, value, outfile=None):
|
def gconfset(self, path, keytype, value, outfile=None):
|
||||||
|
'''
|
||||||
|
gconfset PATH KEYTYPE VALUE [OUTFILE]
|
||||||
|
Set the given gconf PATH, with type KEYTYPE, to the given value.
|
||||||
|
OUTFILE defaults to /etc/gconf/gconf.xml.defaults if not given.
|
||||||
|
Example:
|
||||||
|
gconfset /apps/metacity/general/num_workspaces int 1
|
||||||
|
'''
|
||||||
if outfile is None:
|
if outfile is None:
|
||||||
outfile = self._out("etc/gconf/gconf.xml.defaults")
|
outfile = self._out("etc/gconf/gconf.xml.defaults")
|
||||||
check_call(["gconftool-2", "--direct",
|
check_call(["gconftool-2", "--direct",
|
||||||
@ -229,10 +329,36 @@ class LoraxTemplateRunner(object):
|
|||||||
"--set", "--type", keytype, path, value])
|
"--set", "--type", keytype, path, value])
|
||||||
|
|
||||||
def log(self, msg):
|
def log(self, msg):
|
||||||
|
'''
|
||||||
|
log MESSAGE
|
||||||
|
Emit the given log message. Be sure to put it in quotes!
|
||||||
|
Example:
|
||||||
|
log "Reticulating splines, please wait..."
|
||||||
|
'''
|
||||||
logger.info(msg)
|
logger.info(msg)
|
||||||
|
|
||||||
def runcmd(self, *cmdlist):
|
def runcmd(self, *cmdlist):
|
||||||
'''Note that we need full paths for everything here'''
|
'''
|
||||||
|
runcmd CMD [--chdir=DIR] [ARG ...]
|
||||||
|
Run the given command with the given arguments.
|
||||||
|
If "--chdir=DIR" is given, change to the named directory
|
||||||
|
before executing the command.
|
||||||
|
|
||||||
|
NOTE: All paths given MUST be COMPLETE, ABSOLUTE PATHS to the file
|
||||||
|
or files mentioned. ${root}/${inroot}/${outroot} are good for
|
||||||
|
constructing these paths.
|
||||||
|
|
||||||
|
FURTHER NOTE: Please use this command only as a last resort!
|
||||||
|
Whenever possible, you should use the existing template commands.
|
||||||
|
If the existing commands don't do what you need, fix them!
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
(this should be replaced with a "find" function)
|
||||||
|
runcmd find ${root} -name "*.pyo" -type f -delete
|
||||||
|
%for f in find(root, name="*.pyo"):
|
||||||
|
remove ${f}
|
||||||
|
%endfor
|
||||||
|
'''
|
||||||
chdir = lambda: None
|
chdir = lambda: None
|
||||||
cmd = cmdlist
|
cmd = cmdlist
|
||||||
if cmd[0].startswith("--chdir="):
|
if cmd[0].startswith("--chdir="):
|
||||||
@ -242,10 +368,23 @@ class LoraxTemplateRunner(object):
|
|||||||
check_call(cmd, preexec_fn=chdir)
|
check_call(cmd, preexec_fn=chdir)
|
||||||
|
|
||||||
def installpkg(self, *pkgs):
|
def installpkg(self, *pkgs):
|
||||||
|
'''
|
||||||
|
installpkg PKGGLOB [PKGGLOB ...]
|
||||||
|
Request installation of all packages matching the given globs.
|
||||||
|
Note that this is just a *request* - nothing is *actually* installed
|
||||||
|
until the 'run_pkg_transaction' command is given.
|
||||||
|
'''
|
||||||
for p in pkgs:
|
for p in pkgs:
|
||||||
self.yum.install(pattern=p)
|
self.yum.install(pattern=p)
|
||||||
|
|
||||||
def removepkg(self, *pkgs):
|
def removepkg(self, *pkgs):
|
||||||
|
'''
|
||||||
|
removepkg PKGGLOB [PKGGLOB...]
|
||||||
|
Delete the named package(s).
|
||||||
|
IMPLEMENTATION NOTES:
|
||||||
|
RPM scriptlets (%preun/%postun) are *not* run.
|
||||||
|
Files are deleted, but directories are left behind.
|
||||||
|
'''
|
||||||
for p in pkgs:
|
for p in pkgs:
|
||||||
filepaths = [f.lstrip('/') for f in self._filelist(p)]
|
filepaths = [f.lstrip('/') for f in self._filelist(p)]
|
||||||
# TODO: also remove directories that aren't owned by anything else
|
# TODO: also remove directories that aren't owned by anything else
|
||||||
@ -256,6 +395,11 @@ class LoraxTemplateRunner(object):
|
|||||||
logger.debug("removepkg %s: no files to remove!", p)
|
logger.debug("removepkg %s: no files to remove!", p)
|
||||||
|
|
||||||
def run_pkg_transaction(self):
|
def run_pkg_transaction(self):
|
||||||
|
'''
|
||||||
|
run_pkg_transaction
|
||||||
|
Actually install all the packages requested by previous 'installpkg'
|
||||||
|
commands.
|
||||||
|
'''
|
||||||
self.yum.buildTransaction()
|
self.yum.buildTransaction()
|
||||||
self.yum.repos.setProgressBar(LoraxDownloadCallback())
|
self.yum.repos.setProgressBar(LoraxDownloadCallback())
|
||||||
self.yum.processTransaction(callback=LoraxTransactionCallback(),
|
self.yum.processTransaction(callback=LoraxTransactionCallback(),
|
||||||
@ -263,6 +407,16 @@ class LoraxTemplateRunner(object):
|
|||||||
self.yum.closeRpmDB()
|
self.yum.closeRpmDB()
|
||||||
|
|
||||||
def removefrom(self, pkg, *globs):
|
def removefrom(self, pkg, *globs):
|
||||||
|
'''
|
||||||
|
removefrom PKGGLOB [--allbut] FILEGLOB [FILEGLOB...]
|
||||||
|
Remove all files matching the given file globs from the package
|
||||||
|
(or packages) named.
|
||||||
|
If '--allbut' is used, all the files from the given package(s) will
|
||||||
|
be removed *except* the ones which match the file globs.
|
||||||
|
Examples:
|
||||||
|
removefrom usbutils /usr/bin/*
|
||||||
|
removefrom xfsprogs --allbut /sbin/*
|
||||||
|
'''
|
||||||
cmd = "%s %s" % (pkg, " ".join(globs)) # save for later logging
|
cmd = "%s %s" % (pkg, " ".join(globs)) # save for later logging
|
||||||
keepmatches = False
|
keepmatches = False
|
||||||
if globs[0] == '--allbut':
|
if globs[0] == '--allbut':
|
||||||
|
Loading…
Reference in New Issue
Block a user