summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael DeHaan <mdehaan@redhat.com>2008-04-15 17:34:50 -0400
committerMichael DeHaan <mdehaan@redhat.com>2008-04-15 17:34:50 -0400
commit2ccbb4b130afac3d1707433b3988259ea109db7f (patch)
tree40b7a789997832f510acc7bed20a851f26f1cdbb
parent51119d1acc532cfad68b9fe4a1daa945fe7cd3f0 (diff)
downloadthird_party-cobbler-2ccbb4b130afac3d1707433b3988259ea109db7f.tar.gz
third_party-cobbler-2ccbb4b130afac3d1707433b3988259ea109db7f.tar.xz
third_party-cobbler-2ccbb4b130afac3d1707433b3988259ea109db7f.zip
Replaced the existing cobbler pre/post install triggers system with a much more flexible model that (for each system) passes in the following. First arg: the word "system" or "profile", Second arg: the name of the said system or profile, Third: the MAC if available, Fourth: the IP. This is all logged by a default "status" trigger to /var/log/cobbler/install.log, for being read by the soon-to-be-revamped cobbler check. The check system logs all of this in order, followed by the word "start" or "stop", followed by the number of seconds since Epoch.
-rw-r--r--CHANGELOG1
-rw-r--r--Makefile1
-rw-r--r--cobbler.spec3
-rw-r--r--cobbler/action_status.py5
-rw-r--r--cobbler/action_sync.py56
-rw-r--r--cobbler/remote.py32
-rw-r--r--cobbler/settings.py2
-rw-r--r--cobbler/utils.py10
-rw-r--r--config/cobblerd_rotate7
-rw-r--r--config/settings2
-rw-r--r--kickstarts/sample.ks1
-rw-r--r--scripts/install_trigger.cgi (renamed from scripts/post_install_trigger.cgi)34
-rw-r--r--setup.py5
-rw-r--r--triggers/status_post.trigger16
-rw-r--r--triggers/status_pre.trigger16
15 files changed, 142 insertions, 49 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 0713969..d1fb79d 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -20,6 +20,7 @@ Cobbler CHANGELOG
- now possible to override snippets on a profile/system specific basis
- provide a different default sample kickstart for imports of F8 and later
- support for kerberos authentication
+- revamped pre/post install triggers system (triggered via cgi from kickstart wget)
- ??? - 0.8.3
- Make createrepo get run for local cobbler reposync invocations as needed
diff --git a/Makefile b/Makefile
index bc71166..b8e5d0a 100644
--- a/Makefile
+++ b/Makefile
@@ -55,6 +55,7 @@ devinstall:
webtest: devinstall
/sbin/service cobblerd restart
/sbin/service httpd restart
+ chmod +x /var/www/cgi-bin/cobbler/*.cgi
sdist: clean messages updatewui
python setup.py sdist
diff --git a/cobbler.spec b/cobbler.spec
index 9b775cd..5e63f48 100644
--- a/cobbler.spec
+++ b/cobbler.spec
@@ -163,11 +163,14 @@ test "x$RPM_BUILD_ROOT" != "x" && rm -rf $RPM_BUILD_ROOT
%dir /var/lib/cobbler/triggers/delete/repo/post
%dir /var/lib/cobbler/triggers/sync/pre
%dir /var/lib/cobbler/triggers/sync/post
+%dir /var/lib/cobbler/triggers/install/pre
%dir /var/lib/cobbler/triggers/install/post
%dir /var/lib/cobbler/snippets/
%defattr(744,root,root)
%config(noreplace) /var/lib/cobbler/triggers/sync/post/restart-services.trigger
+%config(noreplace) /var/lib/cobbler/triggers/install/pre/status_pre.trigger
+%config(noreplace) /var/lib/cobbler/triggers/install/post/status_post.trigger
%defattr(664,root,root)
%config(noreplace) /var/lib/cobbler/settings
diff --git a/cobbler/action_status.py b/cobbler/action_status.py
index 7366060..703bf41 100644
--- a/cobbler/action_status.py
+++ b/cobbler/action_status.py
@@ -100,6 +100,11 @@ class BootStatusReport:
tracking will be incomplete. This should be noted in the docs.
"""
+
+ print "NOTE: this function is being replaced right now. Stay tuned!"
+ return 0
+
+
api = cobbler_api.BootAPI()
apache_results = self.scan_apache_logfiles()
diff --git a/cobbler/action_sync.py b/cobbler/action_sync.py
index 1e65e42..5b7b546 100644
--- a/cobbler/action_sync.py
+++ b/cobbler/action_sync.py
@@ -376,7 +376,8 @@ class BootSync:
meta.update(ksmeta) # make available at top level
meta["yum_repo_stanza"] = self.generate_repo_stanza(g,True)
meta["yum_config_stanza"] = self.generate_config_stanza(g,True)
- meta["kickstart_done"] = self.generate_kickstart_signal(g, None)
+ meta["kickstart_done"] = self.generate_kickstart_signal(0, g, None)
+ meta["kickstart_start"] = self.generate_kickstart_signal(1, g, None)
meta["kernel_options"] = utils.hash_to_string(meta["kernel_options"])
kfile = open(kickstart_path)
self.templar.render(kfile, meta, dest, g)
@@ -386,40 +387,56 @@ class BootSync:
msg = "err_kickstart2"
raise CX(_("Error while rendering kickstart file %(src)s to %(dest)s") % { "src" : kickstart_path, "dest" : dest })
- def generate_kickstart_signal(self, profile, system=None):
+ def generate_kickstart_signal(self, is_pre=0, profile=None, system=None):
"""
- Do things that we do at the end of kickstarts...
- * signal the status watcher we're done
- * disable PXE if needed
- * save the original kickstart file for debug
+ Do things that we do at the start/end of kickstarts...
+ * start: signal the status watcher we're starting
+ * end: signal the status watcher we're done
+ * end: disable PXE if needed
+ * end: save the original kickstart file for debug
"""
# FIXME: watcher is more of a request than a packaged file
# we should eventually package something and let it do something important"
- pattern1 = "wget \"http://%s/cgi-bin/cobbler/nopxe.cgi?system=%s\""
- pattern2 = "wget \"http://%s/cobbler/%s/%s/ks.cfg\" -O /root/cobbler.ks"
- pattern3 = "wget \"http://%s/cgi-bin/cobbler/post_install_trigger.cgi?system=%s\""
+
+ nopxe = "\nwget \"http://%s/cgi-bin/cobbler/nopxe.cgi?system=%s\""
+ saveks = "\nwget \"http://%s/cobbler/%s/%s/ks.cfg\" -O /root/cobbler.ks"
+ runpost = "\nwget \"http://%s/cgi-bin/cobbler/install_trigger.cgi?mode=post&%s=%s\""
+ runpre = "\nwget \"http://%s/cgi-bin/cobbler/install_trigger.cgi?mode=pre&%s=%s\""
+ what = "profile"
blend_this = profile
if system:
+ what = "system"
blend_this = system
blended = utils.blender(self.api, False, blend_this)
kickstart = blended.get("kickstart",None)
buf = ""
+ srv = blended["http_server"]
if system is not None:
- if str(self.settings.pxe_just_once).upper() in [ "1", "Y", "YES", "TRUE" ]:
- buf = buf + "\n" + pattern1 % (blended["http_server"], system.name)
- if kickstart and os.path.exists(kickstart):
- buf = buf + "\n" + pattern2 % (blended["http_server"], "kickstarts_sys", system.name)
- if self.settings.run_post_install_trigger:
- buf = buf + "\n" + pattern3 % (blended["http_server"], system.name)
+ if not is_pre:
+ if str(self.settings.pxe_just_once).upper() in [ "1", "Y", "YES", "TRUE" ]:
+ buf = buf + nopxe % (srv, system.name)
+ if kickstart and os.path.exists(kickstart):
+ buf = buf + saveks % (srv, "kickstarts_sys", system.name)
+ if self.settings.run_install_trigger:
+ buf = buf + runpost % (srv, what, system.name)
+ else:
+ if self.settings.run_install_trigger:
+ buf = buf + runpre % (srv, what, system.name)
else:
- if kickstart and os.path.exists(kickstart):
- buf = buf + "\n" + pattern2 % (blended["http_server"], "kickstarts", profile.name)
-
+ if not is_pre:
+ if kickstart and os.path.exists(kickstart):
+ buf = buf + saveks % (srv, "kickstarts", profile.name)
+ if self.settings.run_install_trigger:
+ buf = buf + runpost % (srv, what, profile.name)
+ else:
+ if self.settings.run_install_trigger:
+ buf = buf + runpre % (srv, what, profile.name)
+
return buf
def get_repo_segname(self, is_profile):
@@ -560,7 +577,8 @@ class BootSync:
meta.update(ksmeta) # make available at top level
meta["yum_repo_stanza"] = self.generate_repo_stanza(s, False)
meta["yum_config_stanza"] = self.generate_config_stanza(s, False)
- meta["kickstart_done"] = self.generate_kickstart_signal(profile, s)
+ meta["kickstart_done"] = self.generate_kickstart_signal(0, profile, s)
+ meta["kickstart_start"] = self.generate_kickstart_signal(1, profile, s)
meta["kernel_options"] = utils.hash_to_string(meta["kernel_options"])
kfile = open(kickstart_path)
self.templar.render(kfile, meta, dest, s)
diff --git a/cobbler/remote.py b/cobbler/remote.py
index f7e2226..b606bbc 100644
--- a/cobbler/remote.py
+++ b/cobbler/remote.py
@@ -230,26 +230,28 @@ class CobblerXMLRPCInterface:
systems.add(obj,save=True,with_triggers=False,with_sync=False,quick_pxe_update=True)
return True
- def run_post_install_triggers(self,name,token=None):
+ def run_install_triggers(self,mode,objtype,name,mac,ip,token=None):
+
"""
- This is a feature used to run the post install trigger.
- It passes the system named "name" to the trigger. Disabled by default as
- this requires public API access and is technically a read-write operation.
+ This is a feature used to run the pre/post install triggers.
+ See CobblerTriggers on Wiki for details
"""
- self.log("run_post_install_triggers",token=token)
- # used by postinstalltrigger.cgi
- self.api.clear()
- self.api.deserialize()
- if not self.api.settings().run_post_install_trigger:
- # feature disabled!
+ self.log("run_install_triggers",token=token)
+
+ if mode != "pre" and mode != "post":
return False
- systems = self.api.systems()
- obj = systems.find(name=name)
- if obj == None:
- # system not found!
+ if objtype != "system" and objtype !="profile":
return False
- utils.run_triggers(obj, "/var/lib/cobbler/triggers/install/post/*")
+
+ # the trigger script is called with name,mac, and ip as arguments 1,2, and 3
+ # we do not do API lookups here because they are rather expensive at install
+ # time if reinstalling all of a cluster all at once.
+ # we can do that at "cobbler check" time.
+
+ utils.run_triggers(None, "/var/lib/cobbler/triggers/install/%s/*" % mode, additional=[objtype,name,mac,ip])
+
+
return True
def _refresh(self):
diff --git a/cobbler/settings.py b/cobbler/settings.py
index bc16835..9066d7d 100644
--- a/cobbler/settings.py
+++ b/cobbler/settings.py
@@ -61,7 +61,7 @@ DEFAULTS = {
"manage_dhcp_mode" : "isc",
"next_server" : "127.0.0.1",
"pxe_just_once" : 0,
- "run_post_install_trigger" : 0,
+ "run_install_trigger" : 1,
"server" : "127.0.0.1",
"snippetsdir" : "/var/lib/cobbler/snippets",
"syslog_port" : 25150,
diff --git a/cobbler/utils.py b/cobbler/utils.py
index 8a09025..0f09345 100644
--- a/cobbler/utils.py
+++ b/cobbler/utils.py
@@ -430,7 +430,7 @@ def hash_to_string(hash):
buffer = buffer + str(key) + "=" + str(value) + " "
return buffer
-def run_triggers(ref,globber):
+def run_triggers(ref,globber,additional=[]):
"""
Runs all the trigger scripts in a given directory.
ref can be a cobbler object, if not None, the name will be passed
@@ -447,10 +447,12 @@ def run_triggers(ref,globber):
# skip .rpmnew files that may have been installed
# in the triggers directory
continue
+ arglist = [ file ]
if ref:
- rc = sub_process.call([file,ref.name], shell=False)
- else:
- rc = sub_process.call([file], shell=False)
+ arglist.append(ref.name)
+ for x in additional:
+ arglist.append(x)
+ rc = sub_process.call(arglist, shell=False)
except:
print _("Warning: failed to execute trigger: %s" % file)
continue
diff --git a/config/cobblerd_rotate b/config/cobblerd_rotate
index 0e4bcbf..c7a8b19 100644
--- a/config/cobblerd_rotate
+++ b/config/cobblerd_rotate
@@ -21,3 +21,10 @@
fi
endscript
}
+
+/var/log/cobbler/install.log {
+ missingok
+ notifempty
+ rotate 4
+ weekly
+}
diff --git a/config/settings b/config/settings
index 8fc0fdf..33eb4b1 100644
--- a/config/settings
+++ b/config/settings
@@ -35,7 +35,7 @@ manage_dhcp: 0
manage_dhcp_mode: isc
next_server: '127.0.0.1'
pxe_just_once: 0
-run_post_install_trigger: 0
+run_install_trigger: 1
server: '127.0.0.1'
snippetsdir: /var/lib/cobbler/snippets
syslog_port: 25150
diff --git a/kickstarts/sample.ks b/kickstarts/sample.ks
index 5208ed7..1a7b731 100644
--- a/kickstarts/sample.ks
+++ b/kickstarts/sample.ks
@@ -39,6 +39,7 @@ zerombr
# Magically figure out how to partition this thing
SNIPPET::partition_select
+$kickstart_start
%packages
diff --git a/scripts/post_install_trigger.cgi b/scripts/install_trigger.cgi
index 4a79c8b..493591f 100644
--- a/scripts/post_install_trigger.cgi
+++ b/scripts/install_trigger.cgi
@@ -11,7 +11,7 @@
# if the triggers are enabled in the settings file.
#
# (C) Tim Verhoeven <tim.verhoeven.be@gmail.com>, 2007
-# tweaked: Michael DeHaan <mdehaan@redhat.com>
+# tweaked: Michael DeHaan <mdehaan@redhat.com>, 2007-2008
import cgi
import cgitb
@@ -41,17 +41,37 @@ def parse_query():
form = cgi.parse()
+ mac = "?"
+ if os.environ.has_key("HTTP_X_RHN_PROVISIONING_MAC_0"):
+ devicepair = os.environ["HTTP_X_RHN_PROVISIONING_MAC_0"]
+ mac = devicepair.split()[1].strip()
+
+ ip = "?"
+ if os.environ.has_key("REMOTE_ADDR"):
+ ip = os.environ["REMOTE_ADDR"]
+
+ name = "?"
+ objtype = "?"
if form.has_key("system"):
- return form["system"][0]
- return 0
+ name = form["system"][0]
+ objtype = "system"
+ elif form.has_key("profile"):
+ name = form["profile"][0]
+ objtype = "profile"
+
+ mode = "?"
+ if form.has_key("mode"):
+ mode = form["mode"][0]
+
+ return (mode,objtype,name,mac,ip)
-def invoke(name):
+def invoke(mode,objtype,name,mac,ip):
"""
Determine if this feature is enabled.
"""
xmlrpc_server = ServerProxy(XMLRPC_SERVER)
- print xmlrpc_server.run_post_install_triggers(name)
+ print xmlrpc_server.run_install_triggers(mode,objtype,name,mac,ip)
return True
@@ -66,7 +86,7 @@ def header():
if __name__ == "__main__":
cgitb.enable(format='text')
header()
- name = parse_query()
- invoke(name)
+ (mode,objtype,name,mac,ip) = parse_query()
+ invoke(mode,objtype,name,mac,ip)
diff --git a/setup.py b/setup.py
index 6d4a1cd..c8a6c99 100644
--- a/setup.py
+++ b/setup.py
@@ -65,7 +65,7 @@ if __name__ == "__main__":
(modpython, ['scripts/index.py']),
# cgi files
(cgipath, ['scripts/findks.cgi', 'scripts/nopxe.cgi']),
- (cgipath, ['scripts/post_install_trigger.cgi']),
+ (cgipath, ['scripts/install_trigger.cgi']),
# miscellaneous config files
(rotpath, ['config/cobblerd_rotate']),
@@ -192,7 +192,8 @@ if __name__ == "__main__":
("%sdelete/repo/pre" % trigpath, []),
("%sdelete/repo/post" % trigpath, []),
("%sdelete/repo/post" % trigpath, []),
- ("%sinstall/post" % trigpath, []),
+ ("%sinstall/pre" % trigpath, [ "triggers/status_pre.trigger"]),
+ ("%sinstall/post" % trigpath, [ "triggers/status_post.trigger"]),
("%ssync/pre" % trigpath, []),
("%ssync/post" % trigpath, [ "triggers/restart-services.trigger" ])
],
diff --git a/triggers/status_post.trigger b/triggers/status_post.trigger
new file mode 100644
index 0000000..32934c8
--- /dev/null
+++ b/triggers/status_post.trigger
@@ -0,0 +1,16 @@
+#!/usr/bin/python
+
+import os
+import sys
+import time
+
+objtype = sys.argv[1] # "system" or "profile"
+name = sys.argv[2] # name of system or profile
+mac = sys.argv[3] # mac or "?"
+ip = sys.argv[4] # ip or "?"
+
+fd = open("/var/log/cobbler/install.log","a+")
+fd.write("%s\t%s\t%s\t%s\tstop\t%s\n" % (objtype,name,mac,ip,time.time()))
+fd.close()
+
+sys.exit(0)
diff --git a/triggers/status_pre.trigger b/triggers/status_pre.trigger
new file mode 100644
index 0000000..385beaa
--- /dev/null
+++ b/triggers/status_pre.trigger
@@ -0,0 +1,16 @@
+#!/usr/bin/python
+
+import os
+import sys
+import time
+
+objtype = sys.argv[1] # "system" or "profile"
+name = sys.argv[2] # name of system or profile
+mac = sys.argv[3] # mac or "?"
+ip = sys.argv[4] # ip or "?"
+
+fd = open("/var/log/cobbler/install.log","a+")
+fd.write("%s\t%s\t%s\t%s\tstart\t%s\n" % (objtype,name,mac,ip,time.time()))
+fd.close()
+
+sys.exit(0)