Greetings,
The following patches are intended to replace cobbler's use of syslog=$server. This set of patches introduces a new snippet intended to run in %pre. The snippet will download a python script called 'anamon.py' from your cobbler server. This script "borrows" _heavily_ code written by Mike McLean which is included in koji. This service will monitor your installing system and send logfile changes back to your cobbler server using xmlrpclib. In addition to just /tmp/anaconda.log, the script will monitor your installation for changes to the following files: * /tmp/anaconda.log * /tmp/syslog * /tmp/lvmout * /tmp/ks.cfg * /tmp/ks-script.log * /tmp/anacdump.txt * /tmp/modprobe.conf * /mnt/sysimage/root/install.log * /mnt/sysimage/tmp/install.log * /mnt/sysimage/root/upgrade.log * /mnt/sysimage/tmp/upgrade.log
Any changes to these files are sent incrementally back to the server. Note that the anaconda traceback file '/tmp/anacdump.txt' is included in this list. Having this file sent back to the cobbler server can be very useful for failure analysis.
This service is disabled by default and controlled using the anamon_enabled option in /etc/cobbler/settings.
The patches are included in this thread, and also available at git://fedorapeople.org/~jlaska/cobbler.git
Thanks, James
--- cobbler/pxegen.py | 22 ++++++++++++++++++++-- 1 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/cobbler/pxegen.py b/cobbler/pxegen.py index 4ea9dee..6d9f864 100644 --- a/cobbler/pxegen.py +++ b/cobbler/pxegen.py @@ -108,15 +108,33 @@ class PXEGen: NOTE: this has to be done for both tftp and http methods """ # copy is a 4-letter word but tftpboot runs chroot, thus it's required. + errors = list() for d in self.distros: - self.copy_single_distro_files(d) + try: + self.copy_single_distro_files(d) + except CX, e: + errors.append(e) + print e.value + + # FIXME: using logging module so this ends up in cobbler.log? + if len(errors) > 0: + raise CX(_("Error(s) encountered while copying distro files"))
def copy_images(self): """ Like copy_distros except for images. """ + errors = list() for i in self.images: - self.copy_single_image_files(i) + try: + self.copy_single_image_files(i) + except CX, e: + errors.append(e) + print e.value + + # FIXME: using logging module so this ends up in cobbler.log? + if len(errors) > 0: + raise CX(_("Error(s) encountered while copying image files"))
def copy_single_distro_files(self, d): for dirtree in [self.bootloc, self.settings.webdir]:
James Laska wrote:
cobbler/pxegen.py | 22 ++++++++++++++++++++-- 1 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/cobbler/pxegen.py b/cobbler/pxegen.py index 4ea9dee..6d9f864 100644 --- a/cobbler/pxegen.py +++ b/cobbler/pxegen.py @@ -108,15 +108,33 @@ class PXEGen: NOTE: this has to be done for both tftp and http methods """ # copy is a 4-letter word but tftpboot runs chroot, thus it's required.
errors = list() for d in self.distros:
self.copy_single_distro_files(d)
try:
self.copy_single_distro_files(d)
except CX, e:
errors.append(e)
print e.value
# FIXME: using logging module so this ends up in cobbler.log?
if len(errors) > 0:
raise CX(_("Error(s) encountered while copying distro files"))
def copy_images(self): """ Like copy_distros except for images. """
errors = list() for i in self.images:
self.copy_single_image_files(i)
try:
self.copy_single_image_files(i)
except CX, e:
errors.append(e)
print e.value
# FIXME: using logging module so this ends up in cobbler.log?
if len(errors) > 0:
raise CX(_("Error(s) encountered while copying image files"))
def copy_single_distro_files(self, d): for dirtree in [self.bootloc, self.settings.webdir]:
Applied, thanks!
From: James Laska jlaska@dell-t5400.test.redhat.com
--- cobbler/action_sync.py | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/cobbler/action_sync.py b/cobbler/action_sync.py index 68b5b45..40e5c44 100644 --- a/cobbler/action_sync.py +++ b/cobbler/action_sync.py @@ -136,6 +136,8 @@ class BootSync: utils.rmtree_contents(path) pxelinux_dir = os.path.join(self.bootloc, "pxelinux.cfg") images_dir = os.path.join(self.bootloc, "images") + yaboot_bin_dir = os.path.join(self.bootloc, "ppc") + yaboot_cfg_dir = os.path.join(self.bootloc, "etc") s390_dir = os.path.join(self.bootloc, "s390x") rendered_dir = os.path.join(self.settings.webdir, "rendered") if not os.path.exists(pxelinux_dir): @@ -144,9 +146,15 @@ class BootSync: utils.mkdir(images_dir) if not os.path.exists(rendered_dir): utils.mkdir(rendered_dir) + if not os.path.exists(yaboot_bin_dir): + utils.mkdir(yaboot_bin_dir) + if not os.path.exists(yaboot_cfg_dir): + utils.mkdir(yaboot_cfg_dir) utils.rmtree_contents(os.path.join(self.bootloc, "pxelinux.cfg")) utils.rmtree_contents(os.path.join(self.bootloc, "images")) utils.rmtree_contents(os.path.join(self.bootloc, "s390x")) + utils.rmtree_contents(os.path.join(self.bootloc, "ppc")) + utils.rmtree_contents(os.path.join(self.bootloc, "etc")) utils.rmtree_contents(rendered_dir)
--- MANIFEST.in | 1 + aux/anamon.py | 183 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ cobbler.spec | 4 + setup.py | 8 +++ 4 files changed, 196 insertions(+), 0 deletions(-) create mode 100644 aux/anamon.py
diff --git a/MANIFEST.in b/MANIFEST.in index a367267..43fc677 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -31,5 +31,6 @@ include snippets/* recursive-include po *.pot recursive-include po *.po recursive-include webui_content * +recursive-include aux * recursive-include webui_templates * recursive-include triggers * diff --git a/aux/anamon.py b/aux/anamon.py new file mode 100644 index 0000000..1849bbd --- /dev/null +++ b/aux/anamon.py @@ -0,0 +1,183 @@ +#!/usr/bin/python + +import os +import sys +import string +import time +import re +import md5 +import base64 +import xmlrpclib + +class WatchedFile: + def __init__(self, fn, alias): + self.fn = fn + self.alias = alias + self.reset() + + def reset(self): + self.where = 0 + self.last_size = 0 + self.lfrag='' + self.re_list={} + self.seen_line={} + + def exists(self): + return os.access(self.fn, os.F_OK) + + def lookfor(self,pattern): + self.re_list[pattern] = re.compile(pattern,re.MULTILINE) + self.seen_line[pattern] = 0 + + def seen(self,pattern): + if self.seen_line.has_key(pattern): + return self.seen_line[pattern] + else: + return 0 + + def changed(self): + if not self.exists(): + return 0 + size = os.stat(self.fn)[6] + if size > self.last_size: + self.last_size = size + return 1 + else: + return 0 + + def uploadWrapper(self, blocksize = 262144): + """upload a file in chunks using the uploadFile call""" + retries = 3 + fo = file(self.fn, "r") + totalsize = os.path.getsize(self.fn) + ofs = 0 + md5sum = md5.new() + while True: + lap = time.time() + contents = fo.read(blocksize) + md5sum.update(contents) + size = len(contents) + data = base64.encodestring(contents) + if size == 0: + offset = -1 + digest = md5sum.hexdigest() + sz = ofs + else: + offset = ofs + digest = md5.new(contents).hexdigest() + sz = size + del contents + tries = 0 + while tries <= retries: + debug("upload_log_data('%s', '%s', %s, %s, %s, ...)\n" % (name, self.alias, sz, digest, offset)) + if session.upload_log_data(name, self.alias, sz, digest, offset, data): + break + else: + tries = tries + 1 + if size == 0: + break + ofs += size + fo.close() + + def update(self): + if not self.exists(): + return + if not self.changed(): + return + try: + self.uploadWrapper() + except: + raise + +class MountWatcher: + + def __init__(self,mp): + self.mountpoint = mp + self.zero() + + def zero(self): + self.line='' + self.time = time.time() + + def update(self): + fd = open('/proc/mounts') + found = 0 + while 1: + line = fd.readline() + if not line: + break + parts = string.split(line) + mp = parts[1] + if mp == self.mountpoint: + found = 1 + if line != self.line: + self.line = line + self.time = time.time() + if not found: + self.zero() + fd.close() + + def stable(self): + self.update() + if self.line and (time.time() - self.time > 60): + return 1 + else: + return 0 + +def anamon_loop(): + alog = WatchedFile("/tmp/anaconda.log", "anaconda.log") + alog.lookfor("step installpackages$") + + slog = WatchedFile("/tmp/syslog", "sys.log") + llog = WatchedFile("/tmp/lvmout", "lvmout.log") + kcfg = WatchedFile("/tmp/ks.cfg", "ks.cfg") + scrlog = WatchedFile("/tmp/ks-script.log", "ks-script.log") + dump = WatchedFile("/tmp/anacdump.txt", "anacdump.txt") + mod = WatchedFile("/tmp/modprobe.conf", "modprobe.conf") + ilog = WatchedFile("/mnt/sysimage/root/install.log", "install.log") + ilog2 = WatchedFile("/mnt/sysimage/tmp/install.log", "tmp+install.log") + ulog = WatchedFile("/mnt/sysimage/root/upgrade.log", "upgrade.log") + ulog2 = WatchedFile("/mnt/sysimage/tmp/upgrade.log", "tmp+upgrade.log") + sysimage = MountWatcher("/mnt/sysimage") + watchlist = [alog, slog, dump, scrlog, mod, llog, kcfg] + waitlist = [ilog, ilog2, ulog, ulog2] + + while 1: + time.sleep(5) + + for watch in waitlist: + if alog.seen("step installpackages$") or (sysimage.stable() and watch.exists()): + print "Adding %s to watch list" % watch.alias + watchlist.append(watch) + waitlist.remove(watch) + + for wf in watchlist: + wf.update() + +# process args +name = "" +daemon = 1 +debug = lambda x,**y: None + +n = 0 +while n < len(sys.argv): + arg = sys.argv[n] + if arg == '--name': + n = n+1 + name = sys.argv[n] + elif arg == '--debug': + debug = lambda x,**y: sys.stderr.write(x % y) + elif arg == '--fg': + daemon = 0 + n = n+1 + +session = xmlrpclib.Server("http://dell-t5400.test.redhat.com:80/cobbler_api") + +if daemon: + if not os.fork(): + anamon_loop() + sys._exit(1) + sys.exit(0) +else: + anamon_loop() + diff --git a/cobbler.spec b/cobbler.spec index 9761634..777cfb0 100644 --- a/cobbler.spec +++ b/cobbler.spec @@ -150,8 +150,10 @@ test "x$RPM_BUILD_ROOT" != "x" && rm -rf $RPM_BUILD_ROOT %dir /var/www/cobbler/links %defattr(755,apache,apache) %dir /var/www/cobbler/webui +%dir /var/www/cobbler/aux %defattr(444,apache,apache) /var/www/cobbler/webui/* +/var/www/cobbler/aux/*
%defattr(755,root,root) %{_bindir}/cobbler @@ -195,6 +197,7 @@ test "x$RPM_BUILD_ROOT" != "x" && rm -rf $RPM_BUILD_ROOT %config(noreplace) /etc/httpd/conf.d/cobbler_svc.conf %endif %dir /var/log/cobbler/syslog +%dir /var/log/cobbler/anamon
%defattr(755,root,root) %dir /var/lib/cobbler @@ -261,6 +264,7 @@ test "x$RPM_BUILD_ROOT" != "x" && rm -rf $RPM_BUILD_ROOT %config(noreplace) /var/lib/cobbler/snippets/func_register_if_enabled %config(noreplace) /var/lib/cobbler/snippets/download_config_files %config(noreplace) /var/lib/cobbler/snippets/koan_environment +%config(noreplace) /var/lib/cobbler/snippets/pre_anamon /var/lib/cobbler/elilo-3.8-ia64.efi /var/lib/cobbler/menu.c32 /var/lib/cobbler/yaboot-1.3.14 diff --git a/setup.py b/setup.py index 408c53e..ab62ba4 100644 --- a/setup.py +++ b/setup.py @@ -106,6 +106,7 @@ if __name__ == "__main__": vw_systems = wwwpath + "/systems" vw_profiles = wwwpath + "/profiles" vw_links = wwwpath + "/links" + vw_aux = wwwpath + "/aux" # cgipath = "/var/www/cgi-bin/cobbler" modpython = wwwpath + "/web" modpythonsvc = wwwpath + "/svc" @@ -115,6 +116,7 @@ if __name__ == "__main__": logpath2 = logpath + "/kicklog" logpath3 = logpath + "/syslog" logpath4 = "/var/log/httpd/cobbler" + logpath5 = logpath + "/anamon"
# tftp paths tftp_cfg = "/tftpboot/pxelinux.cfg" @@ -261,6 +263,7 @@ if __name__ == "__main__": (snippetpath, ['snippets/func_register_if_enabled']), (snippetpath, ['snippets/download_config_files']), (snippetpath, ['snippets/koan_environment']), + (snippetpath, ['snippets/pre_anamon']),
# documentation (manpath, ['docs/cobbler.1.gz']), @@ -270,6 +273,7 @@ if __name__ == "__main__": (logpath2, []), (logpath3, []), (logpath4, []), + (logpath5, []),
# web page directories that we own (vw_localmirror, []), @@ -283,6 +287,7 @@ if __name__ == "__main__": (vw_systems, []), (vw_profiles, []), (vw_links, []), + (vw_aux, []),
# zone-specific templates directory (zonepath, []), @@ -336,6 +341,9 @@ if __name__ == "__main__": (wwwcon, ['webui_content/logo-cobbler.png']), (wwwcon, ['webui_content/cobblerweb.css']),
+ # Anamon script + (vw_aux, ['aux/anamon.py']), + # Directories to hold cobbler triggers ("%s/add/distro/pre" % trigpath, []), ("%s/add/distro/post" % trigpath, []),
--- aux/anamon.py | 10 +++++++++- snippets/pre_anamon | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/aux/anamon.py b/aux/anamon.py index aaedf0b..be53da7 100644 --- a/aux/anamon.py +++ b/aux/anamon.py @@ -161,6 +161,8 @@ def anamon_loop():
# process args name = "" +server = "" +port = "80" daemon = 1 debug = lambda x,**y: None
@@ -170,13 +172,19 @@ while n < len(sys.argv): if arg == '--name': n = n+1 name = sys.argv[n] + elif arg == '--server': + n = n+1 + server = sys.argv[n] + elif arg == '--port': + n = n+1 + port = sys.argv[n] elif arg == '--debug': debug = lambda x,**y: sys.stderr.write(x % y) elif arg == '--fg': daemon = 0 n = n+1
-session = xmlrpclib.Server("http://dell-t5400.test.redhat.com:80/cobbler_api") +session = xmlrpclib.Server("http://%s:%s/cobbler_api" % (server, port))
if daemon: if not os.fork(): diff --git a/snippets/pre_anamon b/snippets/pre_anamon index d8001fe..2e16209 100644 --- a/snippets/pre_anamon +++ b/snippets/pre_anamon @@ -1,5 +1,5 @@ #if $str($getVar('anamon_enabled','')) == "1" cd /tmp wget "http://$server/cobbler/aux/anamon.py" -python anamon.py --name "$name" +python anamon.py --name "$name" --server "$server" --port "$http_port" #end if
--- snippets/pre_anamon | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) create mode 100644 snippets/pre_anamon
diff --git a/snippets/pre_anamon b/snippets/pre_anamon new file mode 100644 index 0000000..7816ee3 --- /dev/null +++ b/snippets/pre_anamon @@ -0,0 +1,4 @@ +%pre +cd /tmp +wget "http://$server/cobbler/aux/anamon.py" +python anamon.py --name "$name"
James Laska wrote:
snippets/pre_anamon | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) create mode 100644 snippets/pre_anamon
diff --git a/snippets/pre_anamon b/snippets/pre_anamon new file mode 100644 index 0000000..7816ee3 --- /dev/null +++ b/snippets/pre_anamon @@ -0,0 +1,4 @@ +%pre +cd /tmp +wget "http://$server/cobbler/aux/anamon.py" +python anamon.py --name "$name"
I've merged (but not tested yet) this entire series onto the devel branch.
As a extremely minor sidenote, I'm seeing a /lot/ of "merge" messages in gitk which make the graphs look pretty weird. Generally I think you can run git rebase and not see that? Either way, it's not a problem, but if anyone knows a way to keep gitk a bit cleaner when merging this sort of thing, it might be useful. I occasionally like to look at gitk, but this is not a big deal.
Should have some more comments later (and maybe some suggestions) as I do some more testing.
Likely I'm also going to remove the extra cobblerd fork that listens to syslog (which should make cobblerd take up even less resources and save some kernel options line room -- syslog is only supported on F6 and later, anyway, so RHEL 4 can't benefit).
We can also use some Wiki docs on this if you have some -- perhaps a page on RemoteInstallLogging or equivalent?
--Michael
--- cobbler/remote.py | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 131 insertions(+), 0 deletions(-)
diff --git a/cobbler/remote.py b/cobbler/remote.py index e4155d4..5af1218 100644 --- a/cobbler/remote.py +++ b/cobbler/remote.py @@ -27,10 +27,14 @@ import sys import socket import time import os +import md5 +import base64 import SimpleXMLRPCServer import xmlrpclib import random +import stat import base64 +import fcntl import string import traceback import glob @@ -320,6 +324,133 @@ class CobblerXMLRPCInterface: systems.add(obj,save=True,with_triggers=False,with_sync=False,quick_pxe_update=True) return True
+ def upload_log_data(self, sys_name, file, size, md5sum, offset, data, token=None,**rest): + """ + This is a feature used by the pxe_just_once support, see manpage. + Sets system named "name" to no-longer PXE. Disabled by default as + this requires public API access and is technically a read-write operation. + """ + self._log("upload_log_data (file: '%s', size: %s, offset: %s)" % (file, size, offset), token=token, name=sys_name) + + # FIXME: Check if enabled in self.api.settings() + #if not self.api.settings().pxe_just_once: + if False: + # feature disabled! + return False + + # Find matching system record + systems = self.api.systems() + obj = systems.find(name=sys_name) + if obj == None: + # system not found! + self._log("upload_log_data - system '%s' not found" % sys_name, token=token, name=sys_name) + return False + + return self.__upload_file(sys_name, file, size, md5sum, offset, data) + + def __upload_file(self, sys_name, file, size, md5sum, offset, data): + ''' + system: the name of the system + name: the name of the file + size: size of contents (bytes) + md5: md5sum (hex digest) of contents + data: base64 encoded file contents + offset: the offset of the chunk + files can be uploaded in chunks, if so the md5 and size describe + the chunk rather than the whole file. the offset indicates where + the chunk belongs + the special offset -1 is used to indicate the final chunk''' + contents = base64.decodestring(data) + del data + if offset != -1: + if size is not None: + if size != len(contents): return False + if md5sum is not None: + if md5sum != md5.new(contents).hexdigest(): + return False + + #XXX - have an incoming dir and move after upload complete + # SECURITY - ensure path remains under uploadpath + tt = string.maketrans("/","+") + fn = string.translate(file, tt) + if fn.startswith('..'): + raise CX(_("invalid filename used: %s") % fn) + + # FIXME ... get the base dir from cobbler settings() + udir = "/var/log/cobbler/anamon/%s" % sys_name + if not os.path.isdir(udir): + os.makedirs(udir) + + fn = "%s/%s" % (udir, fn) + try: + st = os.lstat(fn) + except OSError, e: + if e.errno == errno.ENOENT: + pass + else: + raise + else: + if not stat.S_ISREG(st.st_mode): + raise CX(_("destination not a file: %s") % fn) + elif offset == 0: + #first chunk, so file should not exist yet + if not fn.endswith('.log'): + # but we allow .log files to be uploaded multiple times to support + # realtime log-file viewing + raise CX(_("file already exists: %s") % fn) + + fd = os.open(fn, os.O_RDWR | os.O_CREAT, 0666) + # log_error("fd=%r" %fd) + try: + if offset == 0 or (offset == -1 and size == len(contents)): + #truncate file + fcntl.lockf(fd, fcntl.LOCK_EX|fcntl.LOCK_NB) + try: + os.ftruncate(fd, 0) + # log_error("truncating fd %r to 0" %fd) + finally: + fcntl.lockf(fd, fcntl.LOCK_UN) + if offset == -1: + os.lseek(fd,0,2) + else: + os.lseek(fd,offset,0) + #write contents + fcntl.lockf(fd, fcntl.LOCK_EX|fcntl.LOCK_NB, len(contents), 0, 2) + try: + os.write(fd, contents) + # log_error("wrote contents") + finally: + fcntl.lockf(fd, fcntl.LOCK_UN, len(contents), 0, 2) + if offset == -1: + if size is not None: + #truncate file + fcntl.lockf(fd, fcntl.LOCK_EX|fcntl.LOCK_NB) + try: + os.ftruncate(fd, size) + # log_error("truncating fd %r to size %r" % (fd,size)) + finally: + fcntl.lockf(fd, fcntl.LOCK_UN) + if md5sum is not None: + #check final md5sum + sum = md5.new() + fcntl.lockf(fd, fcntl.LOCK_SH|fcntl.LOCK_NB) + try: + # log_error("checking md5sum") + os.lseek(fd,0,0) + while True: + block = os.read(fd, 819200) + if not block: break + sum.update(block) + if md5sum != sum.hexdigest(): + # log_error("md5sum did not match") + #os.close(fd) + return False + finally: + fcntl.lockf(fd, fcntl.LOCK_UN) + finally: + os.close(fd) + return True + def run_install_triggers(self,mode,objtype,name,ip,token=None,**rest):
"""
--- cobbler/settings.py | 1 + installer_templates/settings.template | 7 +++++++ 2 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/cobbler/settings.py b/cobbler/settings.py index 75a678b..e580339 100644 --- a/cobbler/settings.py +++ b/cobbler/settings.py @@ -101,6 +101,7 @@ DEFAULTS = { "yum_post_install_mirror" : 1, "yumdownloader_flags" : "--resolve", "yumreposync_flags" : "-l" + "anamon_enabled" : 0, }
diff --git a/installer_templates/settings.template b/installer_templates/settings.template index e87ccc5..65afa59 100644 --- a/installer_templates/settings.template +++ b/installer_templates/settings.template @@ -267,6 +267,13 @@ spacewalk_url: $spacewalk_url # is UDP and may not be available depending on network/firewall configuration. syslog_port: 25150
+# by default, installs are *not* set to send installation logs to the cobbler +# server. With 'anamon_enabled', kickstart templates may use the pre_anamon +# snippet to allow remote live monitoring of their installations from the +# cobbler server. Installation logs will be stored under +# /var/log/cobbler/anamon. +anamon_enabled: 0 + # locations of the TFTP binary and config file tftpd_bin: /usr/sbin/in.tftpd tftpd_conf: /etc/xinetd.d/tftp
--- snippets/pre_anamon | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/snippets/pre_anamon b/snippets/pre_anamon index 7816ee3..d8001fe 100644 --- a/snippets/pre_anamon +++ b/snippets/pre_anamon @@ -1,4 +1,5 @@ -%pre +#if $str($getVar('anamon_enabled','')) == "1" cd /tmp wget "http://$server/cobbler/aux/anamon.py" python anamon.py --name "$name" +#end if
--- kickstarts/legacy.ks | 1 + kickstarts/sample.ks | 2 +- kickstarts/sample_end.ks | 3 ++- 3 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/kickstarts/legacy.ks b/kickstarts/legacy.ks index 3cb0dc9..b85f93d 100644 --- a/kickstarts/legacy.ks +++ b/kickstarts/legacy.ks @@ -40,6 +40,7 @@ autopart %pre $kickstart_start $SNIPPET('pre_install_network_config') +$SNIPPET('pre_anamon')
%packages
diff --git a/kickstarts/sample.ks b/kickstarts/sample.ks index 478db7b..b0f4da4 100644 --- a/kickstarts/sample.ks +++ b/kickstarts/sample.ks @@ -43,6 +43,7 @@ autopart %pre $kickstart_start $SNIPPET('pre_install_network_config') +$SNIPPET('pre_anamon')
%packages $SNIPPET('func_install_if_enabled') @@ -56,4 +57,3 @@ $SNIPPET('func_register_if_enabled') $SNIPPET('download_config_files') $SNIPPET('koan_environment') $kickstart_done - diff --git a/kickstarts/sample_end.ks b/kickstarts/sample_end.ks index 4d313b4..9098c40 100644 --- a/kickstarts/sample_end.ks +++ b/kickstarts/sample_end.ks @@ -44,8 +44,9 @@ zerombr autopart
%pre -$SNIPPET('pre_install_network_config') $kickstart_start +$SNIPPET('pre_install_network_config') +$SNIPPET('pre_anamon') %end
%packages
--- cobbler/settings.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/cobbler/settings.py b/cobbler/settings.py index e580339..a294945 100644 --- a/cobbler/settings.py +++ b/cobbler/settings.py @@ -100,7 +100,7 @@ DEFAULTS = { "xmlrpc_rw_port" : 25152, "yum_post_install_mirror" : 1, "yumdownloader_flags" : "--resolve", - "yumreposync_flags" : "-l" + "yumreposync_flags" : "-l", "anamon_enabled" : 0, }
--- cobbler/remote.py | 5 ++--- 1 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/cobbler/remote.py b/cobbler/remote.py index 5af1218..6ab1f40 100644 --- a/cobbler/remote.py +++ b/cobbler/remote.py @@ -332,9 +332,8 @@ class CobblerXMLRPCInterface: """ self._log("upload_log_data (file: '%s', size: %s, offset: %s)" % (file, size, offset), token=token, name=sys_name)
- # FIXME: Check if enabled in self.api.settings() - #if not self.api.settings().pxe_just_once: - if False: + # Check if enabled in self.api.settings() + if not self.api.settings().anamon_enabled: # feature disabled! return False
James Laska wrote:
Greetings,
The following patches are intended to replace cobbler's use of syslog=$server. This set of patches introduces a new snippet intended to run in %pre. The snippet will download a python script called 'anamon.py' from your cobbler server. This script "borrows" _heavily_ code written by Mike McLean which is included in koji. This service will monitor your installing system and send logfile changes back to your cobbler server using xmlrpclib. In addition to just /tmp/anaconda.log, the script will monitor your installation for changes to the following files: * /tmp/anaconda.log * /tmp/syslog * /tmp/lvmout * /tmp/ks.cfg * /tmp/ks-script.log * /tmp/anacdump.txt * /tmp/modprobe.conf * /mnt/sysimage/root/install.log * /mnt/sysimage/tmp/install.log * /mnt/sysimage/root/upgrade.log * /mnt/sysimage/tmp/upgrade.log
Any changes to these files are sent incrementally back to the server. Note that the anaconda traceback file '/tmp/anacdump.txt' is included in this list. Having this file sent back to the cobbler server can be very useful for failure analysis.
This service is disabled by default and controlled using the anamon_enabled option in /etc/cobbler/settings.
The patches are included in this thread, and also available at git://fedorapeople.org/~jlaska/cobbler.git
Thanks, James _______________________________________________ cobbler mailing list cobbler@lists.fedorahosted.org https://fedorahosted.org/mailman/listinfo/cobbler
Thanks very much James,
This is a really cool piece of code and is infinitely better than what we have in Cobbler today for remote syslog tracking.
Since this is a big feature and we are going to get Cobbler 1.4 out soon, I'm going to hold this until I have time to pay attention to this. We'll get this in for 1.5 soon and we can begin testing on it. I'll pull from your git tree a little further down the road -- start a new branch for any new features unrelated to this to make merging easier.
Longer term, we can also probably surface this data in Cobbler Web so those logs are viewable there.
Much appreciated!
--Michael
On Thu, 2008-12-11 at 18:36 -0500, Michael DeHaan wrote:
James Laska wrote:
Greetings,
The following patches are intended to replace cobbler's use of syslog=$server. This set of patches introduces a new snippet intended to run in %pre. The snippet will download a python script called 'anamon.py' from your cobbler server. This script "borrows" _heavily_ code written by Mike McLean which is included in koji. This service will monitor your installing system and send logfile changes back to your cobbler server using xmlrpclib. In addition to just /tmp/anaconda.log, the script will monitor your installation for changes to the following files: * /tmp/anaconda.log * /tmp/syslog * /tmp/lvmout * /tmp/ks.cfg * /tmp/ks-script.log * /tmp/anacdump.txt * /tmp/modprobe.conf * /mnt/sysimage/root/install.log * /mnt/sysimage/tmp/install.log * /mnt/sysimage/root/upgrade.log * /mnt/sysimage/tmp/upgrade.log
Any changes to these files are sent incrementally back to the server. Note that the anaconda traceback file '/tmp/anacdump.txt' is included in this list. Having this file sent back to the cobbler server can be very useful for failure analysis.
This service is disabled by default and controlled using the anamon_enabled option in /etc/cobbler/settings.
The patches are included in this thread, and also available at git://fedorapeople.org/~jlaska/cobbler.git
Thanks, James _______________________________________________ cobbler mailing list cobbler@lists.fedorahosted.org https://fedorahosted.org/mailman/listinfo/cobbler
Thanks very much James,
This is a really cool piece of code and is infinitely better than what we have in Cobbler today for remote syslog tracking.
Since this is a big feature and we are going to get Cobbler 1.4 out soon, I'm going to hold this until I have time to pay attention to this. We'll get this in for 1.5 soon and we can begin testing on it. I'll pull from your git tree a little further down the road -- start a new branch for any new features unrelated to this to make merging easier.
There were two patches included in this thread that were outside to scope of anamon support. Do you think these might make 1.4?
[PATCH] Gracefully handle missing kernel/initrd during 'cobbler sync' * https://fedorahosted.org/pipermail/cobbler/2008-December/001940.html
[PATCH] qemu-kvm cannot emulate other architectures, however x86_64 guest can run x86 distros. * https://fedorahosted.org/pipermail/cobbler/2008-December/001907.html
Longer term, we can also probably surface this data in Cobbler Web so those logs are viewable there.
Ooh, good idea.
Much appreciated!
Hope others find it useful, I plan to use this to aid in installation testing.
Thanks, James
cobbler@lists.fedorahosted.org