diff options
-rw-r--r-- | CHANGELOG | 1 | ||||
-rw-r--r-- | Makefile | 1 | ||||
-rw-r--r-- | cobbler.spec | 3 | ||||
-rw-r--r-- | cobbler/action_status.py | 5 | ||||
-rw-r--r-- | cobbler/action_sync.py | 56 | ||||
-rw-r--r-- | cobbler/remote.py | 32 | ||||
-rw-r--r-- | cobbler/settings.py | 2 | ||||
-rw-r--r-- | cobbler/utils.py | 10 | ||||
-rw-r--r-- | config/cobblerd_rotate | 7 | ||||
-rw-r--r-- | config/settings | 2 | ||||
-rw-r--r-- | kickstarts/sample.ks | 1 | ||||
-rw-r--r-- | scripts/install_trigger.cgi (renamed from scripts/post_install_trigger.cgi) | 34 | ||||
-rw-r--r-- | setup.py | 5 | ||||
-rw-r--r-- | triggers/status_post.trigger | 16 | ||||
-rw-r--r-- | triggers/status_pre.trigger | 16 |
15 files changed, 142 insertions, 49 deletions
@@ -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 @@ -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) @@ -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) |