Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
FEATURE - adding ability to grab templated scripts
* Moved scripts/ directory to bin/, since those are all pre-packaged
  executable scripts and /usr/bin is mainly where they go
* Added new scripts/ directory, which will go into /var/lib/cobbler
  alongside kickstarts and snippets. This contains the first script
  for running preseed late-commands.
* Modified sample.seed to call that script
* Modified a few snippets to make them work better with debian/
  ubuntu when using the new templated script functionality
* Minor fix to init script (config/cobblerd) to not use bash-specific
  language constructs, per pull request #461.
  • Loading branch information
jimi-c committed May 9, 2013
1 parent 5666560 commit 955568d
Show file tree
Hide file tree
Showing 22 changed files with 121 additions and 50 deletions.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
36 changes: 16 additions & 20 deletions scripts/services.py → bin/services.py
Expand Up @@ -22,6 +22,7 @@
import yaml
import os
import urllib
import cgi

from cobbler.services import CobblerSvc

Expand All @@ -31,26 +32,21 @@ def application(environ, start_response):

form = {}

if my_uri.find("?") == -1:
# support fake query strings
# something log /cobbler/web/op/ks/server/foo
# which is needed because of xend parser errors
# not tolerating ";" and also libvirt on 5.1 not
# tolerating "&" (nor "&").

# canonicalizes uri, mod_python does this, mod_wsgi does not
my_uri = os.path.realpath(my_uri)

tokens = my_uri.split("/")
tokens = tokens[3:]
label = True
field = ""
for t in tokens:
if label:
field = t
else:
form[field] = t
label = not label
# canonicalizes uri, mod_python does this, mod_wsgi does not
my_uri = os.path.realpath(my_uri)

tokens = my_uri.split("/")
tokens = tokens[3:]
label = True
field = ""
for t in tokens:
if label:
field = t
else:
form[field] = t
label = not label

form["query_string"] = cgi.parse_qs(environ['QUERY_STRING'])

# This MAC header is set by anaconda during a kickstart booted with the
# kssendmac kernel option. The field will appear here as something
Expand Down
File renamed without changes.
File renamed without changes.
9 changes: 9 additions & 0 deletions cobbler/api.py
Expand Up @@ -703,6 +703,15 @@ def generate_bootcfg(self,profile,system):

# ==========================================================================

def generate_script(self,profile,system,name):
self.log("generate_script")
if system:
return self.pxegen.generate_script("system",system,name)
else:
return self.pxegen.generate_script("profile",profile,name)

# ==========================================================================

def check(self, logger=None):
"""
See if all preqs for network booting are valid. This returns
Expand Down
43 changes: 42 additions & 1 deletion cobbler/pxegen.py
Expand Up @@ -745,7 +745,11 @@ def build_kernel_options(self, system, profile, distro, image, arch,
else:
hostname = system.name
else:
hostname = profile.name
# ubuntu at the very least does not like having underscores
# in the hostname.
# FIXME: Really this should remove all characters that are
# forbidden in hostnames
hostname = profile.name.replace("_","")

# At least for debian deployments configured for DHCP networking
# this values are not used, but specifying here avoids questions
Expand Down Expand Up @@ -1003,3 +1007,40 @@ def generate_bootcfg(self,what,name):

return self.templar.render(template_data, blended, None)

def generate_script(self,what,objname,script_name):
if what == "profile":
obj = self.api.find_profile(name=objname)
else:
obj = self.api.find_system(name=objname)

if not obj:
return "# %s named %s not found" % (what,objname)

distro = obj.get_conceptual_parent()
while distro.get_conceptual_parent():
distro = distro.get_conceptual_parent()

blended = utils.blender(self.api, False, obj)

ksmeta = blended.get("ks_meta",{})
try:
del blended["ks_meta"]
except:
pass
blended.update(ksmeta) # make available at top level

if obj.enable_gpxe:
blended['img_path'] = 'http://%s:%s/cobbler/links/%s' % (self.settings.server,self.settings.http_port,distro.name)
else:
blended['img_path'] = os.path.join("/images",distro.name)

template = os.path.normpath(os.path.join("/var/lib/cobbler/scripts",script_name))
if not os.path.exists(template):
return "# script template %s not found" % script_name

template_fh = open(template)
template_data = template_fh.read()
template_fh.close()

return self.templar.render(template_data, blended, None, obj)

4 changes: 4 additions & 0 deletions cobbler/remote.py
Expand Up @@ -1035,6 +1035,10 @@ def generate_bootcfg(self,profile=None,system=None,**rest):
self._log("generate_bootcfg")
return self.api.generate_bootcfg(profile,system)

def generate_script(self,profile=None,system=None,name=None,**rest):
self._log("generate_script, name is %s" % str(name))
return self.api.generate_script(profile,system,name)

def get_blended_data(self,profile=None,system=None):
if profile is not None and profile != "":
obj = self.api.find_profile(profile)
Expand Down
10 changes: 10 additions & 0 deletions cobbler/services.py
Expand Up @@ -93,6 +93,16 @@ def bootcfg(self,profile=None,system=None,**rest):
data = self.remote.generate_bootcfg(profile,system)
return u"%s" % data

def script(self,profile=None,system=None,**rest):
"""
Generate a script based on snippets. Useful for post
or late-action scripts where it's difficult to embed
the script in the response file.
"""
self.__xmlrpc_setup()
data = self.remote.generate_script(profile,system,rest['query_string']['script'][0])
return u"%s" % data

def events(self,user="",**rest):
self.__xmlrpc_setup()
if user == "":
Expand Down
6 changes: 3 additions & 3 deletions config/cobblerd
Expand Up @@ -49,7 +49,7 @@ fi
RETVAL=0

start() {
echo -n $"Starting cobbler daemon: "
echo -n "Starting cobbler daemon: "
if [ -f $SUSE_RELEASE ]; then
startproc -f -p /var/run/$SERVICE.pid /usr/bin/cobblerd $CONFIG_ARGS
rc_status -v
Expand All @@ -71,7 +71,7 @@ start() {
}

stop() {
echo -n $"Stopping cobbler daemon: "
echo -n "Stopping cobbler daemon: "
if [ -f $SUSE_RELEASE ]; then
killproc -TERM /usr/bin/cobblerd
rc_status -v
Expand Down Expand Up @@ -132,7 +132,7 @@ case "$1" in
RETVAL=$?
;;
*)
echo $"Usage: $0 {start|stop|status|restart|condrestart|reload}"
echo "Usage: $0 {start|stop|status|restart|condrestart|reload}"
exit 1
;;
esac
Expand Down
24 changes: 16 additions & 8 deletions kickstarts/sample.seed
Expand Up @@ -12,9 +12,9 @@ d-i keyboard-configuration/variantcode string

# netcfg will choose an interface that has link if possible. This makes it
# skip displaying a list if there is more than one interface.
#set $myhostname = $getVar('hostname',$getVar('name','cobbler')).replace("_","-")
d-i netcfg/choose_interface select auto
d-i netcfg/get_hostname string unassigned-hostname
d-i netcfg/get_domain string unassigned-domain
d-i netcfg/get_hostname string $myhostname

# If non-free firmware is needed for the network or other hardware, you can
# configure the installer to always try to load it, without prompting. Or
Expand All @@ -29,7 +29,7 @@ d-i clock-setup/ntp-server string ntp.ubuntu.com

# Setup the installation source
d-i mirror/country string manual
d-i mirror/http/hostname string $http_server:$http_port
d-i mirror/http/hostname string $http_server
d-i mirror/http/directory string $install_source_directory
d-i mirror/http/proxy string

Expand Down Expand Up @@ -102,6 +102,11 @@ d-i passwd/make-user boolean false
# authentication. Warning: Insecure, not recommended.
# d-i debian-installer/allow_unauthenticated boolean true

# Individual additional packages to install
# wget is REQUIRED otherwise quite a few things won't work
# later in the build (like late-command scripts)
d-i pkgsel/include string wget

# Use the following option to add additional boot parameters for the
# installed system (if supported by the bootloader installer).
# Note: options passed to the installer will be added automatically.
Expand All @@ -125,8 +130,11 @@ $SNIPPET('kickstart_start')
# directly, or use the apt-install and in-target commands to easily install
# packages and run commands in the target system.
# d-i preseed/late_command string [command]
d-i preseed/late_command string chroot /target sh -c ' \
$SNIPPET('download_config_files_deb')
$SNIPPET('post_run_deb')
'; \
$SNIPPET('kickstart_done')
#if $getVar('system_name','') != ''
#set $what = "system"
#else
#set $what = "profile"
#end if
d-i preseed/late_command string wget -O- \
http://$http_server/cblr/svc/op/script/$what/$name/?script=preseed_late_default | \
chroot /target /bin/sh -s
3 changes: 3 additions & 0 deletions scripts/preseed_late_default
@@ -0,0 +1,3 @@
$SNIPPET('post_run_deb')
$SNIPPET('download_config_files')
$SNIPPET('kickstart_done')
19 changes: 10 additions & 9 deletions setup.py
Expand Up @@ -202,17 +202,17 @@ def run(self):
package_dir = {
"cobbler_web": "web/cobbler_web",
},
scripts = [
"scripts/cobbler",
"scripts/cobblerd",
"scripts/cobbler-ext-nodes",
"scripts/koan",
"scripts/ovz-install",
"scripts/cobbler-register",
binscripts = [
"bin/cobbler",
"bin/cobblerd",
"bin/cobbler-ext-nodes",
"bin/koan",
"bin/ovz-install",
"bin/cobbler-register",
],
data_files = proc_data_files([
# tftpd, hide in /usr/sbin
("/usr/sbin", ["scripts/tftpd.py"]),
("/usr/sbin", ["bin/tftpd.py"]),

("%s" % webconfig, ["config/cobbler.conf"]),
("%s" % webconfig, ["config/cobbler_web.conf"]),
Expand All @@ -221,6 +221,7 @@ def run(self):
("installer_templates", ["installer_templates/*"]),
("%skickstarts" % libpath, ["kickstarts/*"]),
("%ssnippets" % libpath, ["snippets/*"]),
("%sscripts" % libpath, ["scripts/*"]),
("%s" % libpath, ["config/distro_signatures.json"]),
("web", ["web/*.*"]),
("%s" % webcontent, ["web/content/*.*"]),
Expand Down Expand Up @@ -313,7 +314,7 @@ def run(self):
("%scobbler/images" % webroot, []),

#A script that isn't really data, wsgi script
("%scobbler/svc/" % webroot, ["scripts/services.py"]),
("%scobbler/svc/" % webroot, ["bin/services.py"]),

# zone-specific templates directory
("%szone_templates" % etcpath, []),
Expand Down
10 changes: 7 additions & 3 deletions snippets/kickstart_done
Expand Up @@ -19,7 +19,7 @@
#else if $breed == 'vmware'
#set nopxe = "\nwget \"http://%s/cblr/svc/op/nopxe/system/%s\" -O /dev/null" % (srv, system_name)
#else if $breed == 'debian' or $breed == 'ubuntu'
#set nopxe = "wget \"http://%s/cblr/svc/op/nopxe/system/%s\" -O /dev/null;" % (srv, system_name)
#set nopxe = "\nwget \"http://%s/cblr/svc/op/nopxe/system/%s\" -O /dev/null" % (srv, system_name)
#else
## default to wget
#set nopxe = "wget \"http://%s/cblr/svc/op/nopxe/system/%s\" -O /dev/null;" % (srv, system_name)
Expand All @@ -34,7 +34,7 @@
#else if $breed == 'vmware'
#set saveks = "\nwget \"http://%s/cblr/svc/op/ks/%s/%s\" -O /var/log/cobbler.ks" % (srv, "system", system_name)
#else if $breed == 'debian' or $breed == 'ubuntu'
#set saveks = "wget \"http://%s/cblr/svc/op/ks/%s/%s\" -O /target/var/log/cobbler.seed;" % (srv, "system", system_name)
#set saveks = "\nwget \"http://%s/cblr/svc/op/ks/%s/%s\" -O /var/log/cobbler.seed" % (srv, "system", system_name)
#end if
#end if
## RUN POST TRIGGER
Expand All @@ -46,7 +46,7 @@
#else if $breed == 'vmware'
#set runpost = "\nwget \"http://%s/cblr/svc/op/trig/mode/post/%s/%s\" -O /dev/null" % (srv, "system", system_name)
#else if $breed == 'debian' or $breed == 'ubuntu'
#set runpost = "wget \"http://%s/cblr/svc/op/trig/mode/post/%s/%s\" -O /dev/null;" % (srv, "system", system_name)
#set runpost = "\nwget \"http://%s/cblr/svc/op/trig/mode/post/%s/%s\" -O /dev/null" % (srv, "system", system_name)
#end if
#end if
#else if $profile_name != ''
Expand All @@ -58,6 +58,8 @@
#set saveks = "\ncurl \"http://%s/cblr/svc/op/ks/%s/%s\" -o /root/cobbler.ks" % (srv, "profile", profile_name)
#else if $breed == 'vmware'
#set saveks = "\nwget \"http://%s/cblr/svc/op/ks/%s/%s\" -O /var/log/cobbler.ks" % (srv, "profile", profile_name)
#else if $breed == 'debian' or $breed == 'ubuntu'
#set saveks = "\nwget \"http://%s/cblr/svc/op/ks/%s/%s\" -O /var/log/cobbler.seed" % (srv, "profile", profile_name)
#end if
#end if
## RUN POST TRIGGER
Expand All @@ -68,6 +70,8 @@
#set runpost = "\ncurl \"http://%s/cblr/svc/op/trig/mode/post/%s/%s\" -o /dev/null" % (srv, "profile", profile_name)
#else if $breed == 'vmware'
#set runpost = "\nwget \"http://%s/cblr/svc/op/trig/mode/post/%s/%s\" -O /dev/null" % (srv, "profile", profile_name)
#else if $breed == 'debian' or $breed == 'ubuntu'
#set runpost = "\nwget \"http://%s/cblr/svc/op/trig/mode/post/%s/%s\" -O /dev/null" % (srv, "profile", profile_name)
#end if
#end if
#end if
Expand Down
7 changes: 1 addition & 6 deletions snippets/post_run_deb
@@ -1,6 +1 @@
## for this script to work put the file somewhere on the cobbler server
## and in 'Template Files' field put /path/to/the/file/some_shell_script.sh=/tmp/some_shell_script.sh
## That will work with 'download_config_files_deb' snippet
#set $run_cmd = '/tmp/some_shell_script.sh; \\'
## put more commands here
#echo $run_cmd
# A general purpose snippet to add late-command actions for preseeds

0 comments on commit 955568d

Please sign in to comment.