I am unable to test these at this time (I get an error from api.py when
it encounters:
import acls
What package/file does this come from?)
Meanwhile, here are two patches. The first moves the builtins into
cheetah_macros and provides documentation. The second adds
cheetah_macros to setup.py and MANIFEST.in (you'll want to check my work).
I'll be as prompt as possible to help resolve any errors that this
untested code may (will) introduce.
~
Dan
>From f4bda090e0f979c3b6295af94e0c64206a9636f3 Mon Sep 17 00:00:00 2001
From: Dan Guernsey <[EMAIL PROTECTED]>
Date: Mon, 1 Sep 2008 21:35:34 -0500
Subject: [PATCH] moved builtins to cheetah_macros with documentation
The builtin methods have been moved out of template_api.py (except for
SNIPPET and sedesc) into /etc/cobbler/cheetah_macros. I have also
provided documentation with examples for each (mostly).
Unlike what I tried with my previous patch, there will be no file for
user-created pure python methods, just cheetah template methods.
---
cobbler/template_api.py | 192 +++++------------------------------
config/cheetah_macros | 253 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 281 insertions(+), 164 deletions(-)
create mode 100644 config/cheetah_macros
diff --git a/cobbler/template_api.py b/cobbler/template_api.py
index e6a4b2a..c81c67a 100644
--- a/cobbler/template_api.py
+++ b/cobbler/template_api.py
@@ -25,6 +25,8 @@ import Cheetah.Template
import os.path
import re
+CHEETAH_MACROS_FILE = '/etc/cobbler/cheetah_macros'
+
# This class is defined using the Cheetah language. Using the 'compile' function
# we can compile the source directly into a python class. This class will allow
# us to define the cheetah builtins.
@@ -36,10 +38,22 @@ BuiltinTemplate = Cheetah.Template.Template.compile(source="\n".join([
# still need to make the snippet's namespace (searchList) available to the
# template calling SNIPPET (done in the other part).
- # TODO: Should this be in its own file? If so, should it go into
- # /var/lib/cobbler or should it go with cobbler's site-package?
- # how about /etc/cobbler/cheetah.conf ? -- mpd
-
+ # Moved the other functions into /etc/cobbler/cheetah_macros
+ # Left SNIPPET here since it is very important.
+
+ # This function can be used in two ways:
+ # Cheetah syntax:
+ #
+ # $SNIPPET('my_snippet')
+ #
+ # SNIPPET syntax:
+ #
+ # SNIPPET::my_snippet
+ #
+ # This follows all of the rules of snippets and advanced snippets. First it
+ # searches for a per-system snippet, then a per-profile snippet, then a
+ # general snippet. If none is found, a comment explaining the error is
+ # substituted.
"#def SNIPPET($file)",
"#set $fullpath = $find_snippet($file)",
"#if $fullpath",
@@ -48,168 +62,11 @@ BuiltinTemplate = Cheetah.Template.Template.compile(source="\n".join([
"# Error: no snippet data for $file",
"#end if",
"#end def",
-
- # Comment every line containing the $pattern given
- "#def comment_lines($filename, $pattern, $commentchar='#')",
- "perl -npe 's/^(.*${pattern}.*)$/${commentchar}\\${1}/' -i '$filename'",
- "#end def",
-
- # Comments every line which contains only the exact pattern.
- "#def comment_lines_exact($filename, $pattern, $commentchar='#')",
- "perl -npe 's/^(${pattern})$/${commentchar}\\${1}/' -f '$filename'",
- "#end def",
-
- # Uncomments every (commented) line containing the pattern
- # Patterns should not contain the #
- "#def uncomment_lines($filename, $pattern, $commentchar='#')",
- "perl -npe 's/^[ \\t]*${commentchar}(.*${pattern}.*)$/\\${1}/' -i '$filename'",
- "#end def",
-
- # Nullify (by changing to 'true') all instances of a given sh command. This
- # does understand lines with multiple commands (separated by ';') and also
- # knows to ignore comments. Consider other options before using this
- # method.
- "#def delete_command($filename, $pattern)",
- "sed -nr '",
- " h",
- " s/^([^#]*)(#?.*)$/\\1/",
- " s/((^|;)[ \\t]*)${pattern}([ \\t]*($|;))/\\1true\\3/g",
- " s/((^|;)[ \\t]*)${pattern}([ \\t]*($|;))/\\1true\\3/g",
- " x",
- " s/^([^#]*)(#?.*)$/\\2/",
- " H",
- " x",
- " s/\\n//",
- " p",
- "' -i '$filename'",
- "#end def",
-
- # Replace a configuration parameter value, or add it if it doesn't exist.
- # Assumes format is [param_name] [value]
- "#def set_config_value($filename, $param_name, $value)",
- "if [ -n \"\\$(grep -Ee '^[ \\t]*${param_name}[ \\t]+' '$filename')\" ]",
- "then",
- " perl -npe 's/^([ \\t]*${param_name}[ \\t]+)[\\x21-\\x7E]*([ \\t]*(#.*)?)$/\\${1}${sedesc($value)}\\${2}/' -i '$filename'",
- "else",
- " echo '$param_name $value' >> '$filename'",
- "fi",
- "#end def",
-
- # Replace a configuration parameter value, or add it if it doesn't exist.
- # Assues format is [param_name] [delimiter] [value], where [delimiter] is
- # usually '='.
- "#def set_config_value_delim($filename, $param_name, $delim, $value)",
- "if [ -n \"\\$(grep -Ee '^[ \\t]*${param_name}[ \\t]*${delim}[ \\t]*' '$filename')\" ]",
- "then",
- " perl -npe 's/^([ \\t]*${param_name}[ \\t]*${delim}[ \\t]*)[\\x21-\\x7E]*([ \\t]*(#.*)?)$/${1}${sedesc($value)}${2}/' -i '$filename'",
- "else",
- " echo '$param_name$delim$value' >> '$filename'",
- "fi",
- "#end def",
-
- # Copy a file from the server to the client.
- "#def copy_over_file($serverfile, $clientfile)",
- "cat << 'EOF' > '$clientfile'",
- "#include $files + $serverfile",
- "EOF",
- "#end def",
-
- # Copy a file from the server and append the contents to a file on the
- # client.
- "#def copy_over_file($serverfile, $clientfile)",
- "cat << 'EOF' >> '$clientfile'",
- "#include $files + $serverfile",
- "EOF",
- "#end def",
-
- # Convenience function: Copy/append several files at once. This accepts a
- # list of tuples. The first element indicates whether to overwrite ('w') or
- # append ('a'). The second element is the file name on both the server and
- # the client (a '/' is prepended on the client side).
- "#def copy_files($filelist)",
- "#for $thisfile in $filelist",
- "#if $thisfile[0] == 'a'",
- "$copy_append_file($thisfile[1], '/' + $thisfile[1])",
- "#else",
- "$copy_over_file($thisfile[1], '/' + $thisfile[1])",
- "#end if",
- "#end for",
- "#end def",
-
- # Append some content to the todo file. NOTE: $todofile must be defined
- # before using this (unless you want unexpected results). Be sure to end
- # the content with 'EOF'
- "#def TODO()",
- "cat << 'EOF' >> '$todofile'",
- "#end def",
-
- # Set the owner, group, and permissions for several files. Assignment can
- # be plain ('p') or recursive. If recursive you can assign everything ('r')
- # or just files ('f'). This method takes a list of tuples. The first element
- # of each indicates which style. The remaining elements are owner, group,
- # and mode respectively. If 'f' is used, an additional element is a find
- # pattern that can further restrict assignments (use '*' if no additional
- # restrict is desired).
- "#def set_permissions($filelist)",
- "#for $file in $filelist",
- "#if $file[0] == 'p'",
- "#if $file[1] != '' and $file[2] != ''",
- "chown '$file[1]:$file[2]' '$file[4]'",
- "#else",
- "#if $file[1] != ''",
- "chown '$file[1]' '$file[4]'",
- "#end if",
- "#if $file[2] != ''",
- "chgrp '$file[2]' '$file[4]'",
- "#end if",
- "#end if",
- "#if $file[3] != ''",
- "chmod '$file[3]' '$file[4]'",
- "#end if",
- "#elif $file[0] == 'r'",
- "#if $file[1] != '' and $file[2] != ''",
- "chown -R '$file[1]:$file[2]' '$file[4]'",
- "#else",
- "#if $file[1] != ''",
- "chown -R '$file[1]' '$file[4]'",
- "#end if",
- "#if $file[2] != ''",
- "chgrp -R '$file[2]' '$file[4]'",
- "#end if",
- "#end if",
- "#if $file[3] != ''",
- "chmod -R '$file[3]' '$file[4]'",
- "#end if",
- "#elif $file[0] == 'f'",
- "#if $file[1] != '' and $file[2] != ''",
- "find $file[4] -name '$file[5]' -type f -exec chown -R '$file[1]:$file[2]' {} \\;",
- "#else",
- "#if $file[1] != ''",
- "find $file[4] -name '$file[5]' -type f -exec chown -R '$file[1]' {} \\;",
- "#end if",
- "#if $file[2] != ''",
- "find $file[4] -name '$file[5]' -type f -exec chgrp -R '$file[2]' {} \\;",
- "#end if",
- "#end if",
- "#if $file[3] != ''",
- "find $file[4] -name '$file[5]' -type f -exec chmod -R '$file[3]' {} \\;",
- "#end if",
- "#end if",
- "#end for",
- "#end def",
-
- # Cheeseball an entire directory.
- "#def includeall($dir)",
- "#import os",
- "#for $file in $os.listdir($snippetsdir + '/' + $dir)",
- "#include $snippetsdir + '/' + $dir + '/' + $file",
- "#end for",
- "#end def",
-
]) + "\n")
+MacrosTemplate = Cheetah.Template.Template.compile(file=CHEETAH_MACROS_FILE)
-class Template(BuiltinTemplate):
+class Template(BuiltinTemplate, MacrosTemplate):
"""
This class will allow us to include any pure python builtin functions.
@@ -270,7 +127,7 @@ class Template(BuiltinTemplate):
def find_snippet(self, file):
"""
Locate the appropriate snippet for the current system and profile.
- This will first check for a per_system snippet, a per_profile snippet,
+ This will first check for a per-system snippet, a per-profile snippet,
and a general snippet. If no snippet is located, it returns None.
"""
if self.varExists('system_name'):
@@ -315,6 +172,13 @@ class Template(BuiltinTemplate):
return result
+ # This function is used by several cheetah methods in cheetah_macros.
+ # It can be used by the end user as well.
+ # Ex: Replace all instances of '/etc/banner' with a value stored in
+ # $new_banner
+ #
+ # sed 's/$sedesc("/etc/banner")/$sedesc($new_banner)/'
+ #
def sedesc(self, value):
"""
Escape a string for use in sed.
diff --git a/config/cheetah_macros b/config/cheetah_macros
new file mode 100644
index 0000000..338bbd4
--- /dev/null
+++ b/config/cheetah_macros
@@ -0,0 +1,253 @@
+
+## Comment every line containing the $pattern given
+## Ex: preserve a record of an old value before changing it.
+##
+## $comment_lines('/etc/resolv.conf', 'nameserver')
+## echo "nameserver 192.168.0.1" >> /etc/resolv.conf
+##
+#def comment_lines($filename, $pattern, $commentchar='#')
+perl -npe 's/^(.*${pattern}.*)$/${commentchar}\${1}/' -i '$filename'
+#end def
+
+## Comments every line which contains only the exact pattern.
+## This one works like comment_lines(), except that a line cannot contain any
+## additional text.
+#def comment_lines_exact($filename, $pattern, $commentchar='#')
+perl -npe 's/^(${pattern})$/${commentchar}\${1}/' -f '$filename'
+#end def
+
+## Uncomments every (commented) line containing the pattern
+## Patterns should not contain the #
+## Ex: enable all the suggested values in the Samba configuration
+## (This isn't the greatest example, but it makes a point)
+##
+## $uncomment_lines('/etc/samba/smb.conf', ';')
+##
+#def uncomment_lines($filename, $pattern, $commentchar='#')
+perl -npe 's/^[ \t]*${commentchar}(.*${pattern}.*)$/\${1}/' -i '$filename'
+#end def
+
+## Nullify (by changing to 'true') all instances of a given sh command. This
+## does understand lines with multiple commands (separated by ';') and also
+## knows to ignore comments. Consider other options before using this
+## method.
+## Ex: remove 'exit 0' commands from a shell script, so that we can append the
+## script and be relatively certain that the new parts will be executed.
+##
+## $delete_command('etc/cron.daily/some_script.sh', 'exit[ \t]*0')
+## echo '# More scipt' >> /etc/cron.daily/some_script.sh
+##
+#def delete_command($filename, $pattern)
+sed -nr '
+ h
+ s/^([^#]*)(#?.*)$/\1/
+ s/((^|;)[ \t]*)${pattern}([ \t]*($|;))/\1true\3/g
+ s/((^|;)[ \t]*)${pattern}([ \t]*($|;))/\1true\3/g
+ x
+ s/^([^#]*)(#?.*)$/\2/
+ H
+ x
+ s/\n//
+ p
+' -i '$filename'
+#end def
+
+## Replace a configuration parameter value, or add it if it doesn't exist.
+## Assumes format is [param_name] [value]
+## Ex: Change the maximum password age to 30 days
+##
+## $set_config_value('/etc/login.defs', 'PASS_MAX_DAYS', '30')
+##
+#def set_config_value($filename, $param_name, $value)
+if [ -n \"\$(grep -Ee '^[ \t]*${param_name}[ \t]+' '$filename')\" ]
+then
+ perl -npe 's/^([ \t]*${param_name}[ \t]+)[\x21-\x7E]*([ \t]*(#.*)?)$/\${1}${sedesc($value)}\${2}/' -i '$filename'
+else
+ echo '$param_name $value' >> '$filename'
+fi
+#end def
+
+## Replace a configuration parameter value, or add it if it doesn't exist.
+## Assues format is [param_name] [delimiter] [value], where [delimiter] is
+## usually '='.
+## This works the same way as set_config_value(), except that this version
+## is used if a character separates a parameter from its value.
+#def set_config_value_delim($filename, $param_name, $delim, $value)
+if [ -n \"\$(grep -Ee '^[ \t]*${param_name}[ \t]*${delim}[ \t]*' '$filename')\" ]
+then
+ perl -npe 's/^([ \t]*${param_name}[ \t]*${delim}[ \t]*)[\x21-\x7E]*([ \t]*(#.*)?)$/${1}${sedesc($value)}${2}/' -i '$filename'
+else
+ echo '$param_name$delim$value' >> '$filename'
+fi
+#end def
+
+## Copy a file from the server to the client.
+## Ex: Copy a template for samba configuration
+##
+## (once at the top of the kickstart template)
+## #set files = $snippetsdir + '/files/'
+## (when you need to copy a file)
+## $copy_over_file('etc/samba/smb.conf', '/etc/samba/smb.conf')
+##
+## Additionally, copied files can be templated:
+## ---------etc/samba/smb.conf-------------
+## ...
+## [global]
+## server string = $profile_name
+## ...
+## ----------------------------------------
+#def copy_over_file($serverfile, $clientfile)
+cat << 'EOF' > '$clientfile'
+#include $files + $serverfile
+EOF
+#end def
+
+## Copy a file from the server and append the contents to a file on the
+## client.
+## This works the same as copy_over_file(), except it appends the file rather
+## than replacing the file.
+#def copy_append_file($serverfile, $clientfile)
+cat << 'EOF' >> '$clientfile'
+#include $files + $serverfile
+EOF
+#end def
+
+## Convenience function: Copy/append several files at once. This accepts a
+## list of tuples. The first element indicates whether to overwrite ('w') or
+## append ('a'). The second element is the file name on both the server and
+## the client (a '/' is prepended on the client side).
+## Ex: copy a template for samba and audit configuration
+##
+## $copy_files([
+## ('w', 'etc/samba/smb.conf'),
+## ('w', 'etc/audit.rules'),
+## ])
+##
+#def copy_files($filelist)
+#for $thisfile in $filelist
+#if $thisfile[0] == 'a'
+$copy_append_file($thisfile[1], '/' + $thisfile[1])
+#else
+$copy_over_file($thisfile[1], '/' + $thisfile[1])
+#end if
+#end for
+#end def
+
+## Append some content to the todo file. NOTE: $todofile must be defined
+## before using this (unless you want unexpected results). Be sure to end
+## the content with 'EOF'
+## Ex: Instruct the admin to set an appropriate nameserver.
+##
+## (once at the top of the kickstart template)
+## #set global $todofile = '/root/kstodo'
+## (as needed)
+## $TODO()
+## Edit /etc/resolv.conf to configure your local nameserver
+## EOF
+##
+## This will prevent inconsistency and accidents. You should avoid using:
+##
+## echo "Edit /etc/resolv.conf..." >> /root/kstodo
+##
+## It's easy to forget to use >> to append instead of >, which will clobber all
+## previous todo notices. It's also easy to forget the filename, was it kstodo
+## or ks-todo?
+#def TODO()
+cat << 'EOF' >> '$todofile'
+#end def
+
+## Set the owner, group, and permissions for several files. Assignment can
+## be plain ('p') or recursive. If recursive you can assign everything ('r')
+## or just files ('f'). This method takes a list of tuples. The first element
+## of each indicates which style. The remaining elements are owner, group,
+## and mode respectively. If 'f' is used, an additional element is a find
+## pattern that can further restrict assignments (use '*' if no additional
+## restrict is desired).
+## NOTE: I used the word 'plain' instead of 'single', because wildcards can
+## still be used in 'plain' mode.
+## Ex: correct the permissions of serveral important files and directories:
+##
+## $set_permissions([
+## ('p', 'root', 'root', '700', '/root'),
+## ('f', 'root', 'root', '600', '/root', '*'),
+## ('r', 'root', 'root', '/etc/cron.*'),
+## ('p', 'root', 'root', '644', '/etc/samba/smb.conf'),
+## ])
+##
+#def set_permissions($filelist)
+#for $file in $filelist
+#if $file[0] == 'p'
+#if $file[1] != '' and $file[2] != ''
+chown '$file[1]:$file[2]' '$file[4]'
+#else
+#if $file[1] != ''
+chown '$file[1]' '$file[4]'
+#end if
+#if $file[2] != ''
+chgrp '$file[2]' '$file[4]'
+#end if
+#end if
+#if $file[3] != ''
+chmod '$file[3]' '$file[4]'
+#end if
+#elif $file[0] == 'r'
+#if $file[1] != '' and $file[2] != ''
+chown -R '$file[1]:$file[2]' '$file[4]'
+#else
+#if $file[1] != ''
+chown -R '$file[1]' '$file[4]'
+#end if
+#if $file[2] != ''
+chgrp -R '$file[2]' '$file[4]'
+#end if
+#end if
+#if $file[3] != ''
+chmod -R '$file[3]' '$file[4]'
+#end if
+#elif $file[0] == 'f'
+#if $file[1] != '' and $file[2] != ''
+find $file[4] -name '$file[5]' -type f -exec chown -R '$file[1]:$file[2]' {} \;
+#else
+#if $file[1] != ''
+find $file[4] -name '$file[5]' -type f -exec chown -R '$file[1]' {} \;
+#end if
+#if $file[2] != ''
+find $file[4] -name '$file[5]' -type f -exec chgrp -R '$file[2]' {} \;
+#end if
+#end if
+#if $file[3] != ''
+find $file[4] -name '$file[5]' -type f -exec chmod -R '$file[3]' {} \;
+#end if
+#end if
+#end for
+#end def
+
+## Cheeseball an entire directory.
+## This will include (in sequence) all file in a given directory into a
+## kickstart template.
+## Ex: include a 'misc' directory of templates
+##
+## $includeall('misc')
+##
+## Now in cobbler/snippets/misc:
+## ---------------avinstall-----------------
+## wget http://some.server.com/some-av-package.tar.gz
+## tar -xzf some-av-package.tar.gz
+## ./some-av-package/install.sh
+## rm some-av-package.tar.gz
+## rm -rf some-av-package
+## -----------------------------------------
+## ---------------fwinstall-----------------
+## wget http://some.server.com/fw-linux-installer.sh
+## chmod +x fw-linux-installer.sh
+## ./fw-linux-installer.sh
+## rm fw-linux-installer.sh
+## -----------------------------------------
+##
+#def includeall($dir)
+#import os
+#for $file in $os.listdir($snippetsdir + '/' + $dir)
+#include $snippetsdir + '/' + $dir + '/' + $file
+#end for
+#end def
+
--
1.5.6.3
>From de219f4ff8874f94269acf234bb802423e577c75 Mon Sep 17 00:00:00 2001
From: Dan Guernsey <[EMAIL PROTECTED]>
Date: Mon, 1 Sep 2008 21:45:05 -0500
Subject: [PATCH] Added cheetah_macros to setup.py and MANIFEST.in
---
MANIFEST.in | 1 +
setup.py | 1 +
2 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/MANIFEST.in b/MANIFEST.in
index 659f04a..e782162 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -15,6 +15,7 @@ include config/users.digest
include config/users.conf
include config/completions
include config/cobbler_bash
+include config/cheetah_macros
recursive-include templates *.template
recursive-include kickstarts *.ks
include docs/cobbler.1.gz
diff --git a/setup.py b/setup.py
index bc26033..1a53f5a 100644
--- a/setup.py
+++ b/setup.py
@@ -80,6 +80,7 @@ if __name__ == "__main__":
(etcpath, ['config/rsync.exclude']),
(etcpath, ['config/users.conf']),
(etcpath, ['config/acls.conf']),
+ (etcpath, ['config/cheetah_macros']),
(initpath, ['config/cobblerd']),
(etcpath, ['config/settings']),
# (bashpath, ['config/cobbler_bash']),
--
1.5.6.3
_______________________________________________
cobbler mailing list
[email protected]
https://fedorahosted.org/mailman/listinfo/cobbler