From 2ccbb4b130afac3d1707433b3988259ea109db7f Mon Sep 17 00:00:00 2001 From: Michael DeHaan Date: Tue, 15 Apr 2008 17:34:50 -0400 Subject: 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. --- cobbler/action_status.py | 5 +++++ cobbler/action_sync.py | 56 ++++++++++++++++++++++++++++++++---------------- cobbler/remote.py | 32 ++++++++++++++------------- cobbler/settings.py | 2 +- cobbler/utils.py | 10 +++++---- 5 files changed, 66 insertions(+), 39 deletions(-) (limited to 'cobbler') 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 -- cgit