summaryrefslogtreecommitdiffstats
path: root/cobbler
diff options
context:
space:
mode:
authormdehaan@mdehaan.rdu.redhat.com <>2007-01-03 17:57:15 -0500
committerJim Meyering <jim@meyering.net>2007-01-03 17:57:15 -0500
commit6d1e1e4a75f82ddf8937e94dd569a12fc702b7ab (patch)
tree6ddec051fc3bacc185e082df69d53eedd71e3c1b /cobbler
parentdf34ff6a18706644308f17b369a0ed3085b92216 (diff)
downloadthird_party-cobbler-6d1e1e4a75f82ddf8937e94dd569a12fc702b7ab.tar.gz
third_party-cobbler-6d1e1e4a75f82ddf8937e94dd569a12fc702b7ab.tar.xz
third_party-cobbler-6d1e1e4a75f82ddf8937e94dd569a12fc702b7ab.zip
Add kickstart pre-signaling to indicate starts in addition to stops.
Diffstat (limited to 'cobbler')
-rw-r--r--cobbler/action_status.py113
-rw-r--r--cobbler/action_sync.py17
-rw-r--r--cobbler/api.py1
-rwxr-xr-xcobbler/cobbler.py13
4 files changed, 119 insertions, 25 deletions
diff --git a/cobbler/action_status.py b/cobbler/action_status.py
index de3da43..2c0fba1 100644
--- a/cobbler/action_status.py
+++ b/cobbler/action_status.py
@@ -19,20 +19,103 @@ import cobbler_msg
class BootStatusReport:
- def __init__(self,config):
- """
- Constructor
- """
- self.config = config
- self.settings = config.settings()
-
- def run(self):
- """
- Returns None if there are no errors, otherwise returns a list
- of things to correct prior to running application 'for real'.
- (The CLI usage is "cobbler check" before "cobbler sync")
- """
- print "..."
- return True
+ def __init__(self,config,mode):
+ """
+ Constructor
+ """
+ self.config = config
+ self.settings = config.settings()
+ self.mode = mode
+
+ # -------------------------------------------------------
+
+ def run(self):
+ """
+ Calculate and print a kickstart-status report.
+ For kickstart trees not in /var/lib/cobbler (or a symlink off of there)
+ tracking will be incomplete. This should be noted in the docs.
+ """
+
+ done = {} # keep track of finish times by IP addr
+ files = {} # keep up with xfer'd files by IP addr
+
+ # gather stats from logfiles, allowing for rotations in the log file ...
+ for i in range(0,6):
+
+ # figure out what logfile to open
+ j = ""
+ if i != 0:
+ j = "%s" % (i-1)
+ fname = "/var/log/cobbler/cobbler%s.log" % j
+
+ # open it if it's there
+ if not os.path.exists(fname):
+ print "no such file: %s" % fname
+ break
+ logfile = open(fname, "r")
+
+ # each line in the file corresponds to an accessed file
+ while(True):
+ data = logfile.readline()
+ if data is None or data == "":
+ break
+
+ # fields are tab delimited
+ # (1) seconds since 1970, in decimal
+ # (2) ASCII date for humans
+ # (3) IP address of requester
+ # (4) HTTP request line
+
+ (epoch, strdate, ip, request) = data.split("\t")
+
+ # HTTP request line is essentially space delimited
+ # (1) method, which should always be GET
+ # (2) filename, which is relative from server root
+ # (3) protocol, such as HTTP/1.1
+
+ (method, filepath, protocol) = request.split(" ")
+
+ # make room in the nested datastructures for report info
+
+ if not done.has_key(ip):
+ done[ip] = [] # list of kickstart finish times
+ if not files.has_key(ip):
+ files[ip] = {} # hash of access times and filenames
+
+ # keep track of when IP addresses's finish. Right now, we don't
+ # care much about profile or system name but can get this later.
+
+ if filepath.find("?system_done") != -1:
+ done[ip].append(epoch)
+ elif filepath.find("?profile_done") != -1:
+ done[ip].append(epoch)
+ else:
+ files[ip][epoch] = filepath
+
+ # FIXME: what's a good way to see when systems START? For FC6+
+ # it will install via yum, so xml and xml.gz files come first.
+ # elsewhere, that's not true.
+
+ logfile.close()
+
+
+ # report on the data found in all of the files, aggregated.
+
+ self.generate_report(files,done)
+ return True
+
+ #-----------------------------------------
+
+ def generate_report(self,files,done):
+ """
+ Given the information about transferred files and kickstart finish times, attempt
+ to produce a report that most describes the state of the system.
+
+ FIXME: just text for now, but should pay attention to self.mode and possibly offer
+ a HTML or XML or YAML version for other apps. Not all, just some alternatives.
+ """
+ print "%s" % files
+ print "%s" % done
+
diff --git a/cobbler/action_sync.py b/cobbler/action_sync.py
index 694425f..10fe3df 100644
--- a/cobbler/action_sync.py
+++ b/cobbler/action_sync.py
@@ -320,19 +320,23 @@ class BootSync:
))
meta["yum_repo_stanza"] = self.generate_repo_stanza(g)
meta["yum_config_stanza"] = self.generate_config_stanza(g)
- meta["kickstart_done"] = self.generate_kickstart_done(g, is_system=False)
+ meta["kickstart_done"] = self.generate_kickstart_signal(g, is_system=False, is_done=True)
+ meta["kickstart_start"] = self.generate_kickstart_signal(g, is_system=False, is_done=False)
self.apply_template(kickstart_path, meta, dest)
except:
traceback.print_exc() # leave this in, for now...
msg = "err_kickstart2"
raise cexceptions.CobblerException(msg,kickstart_path,dest)
- def generate_kickstart_done(self, obj, is_system=False):
- pattern = "wget http://%s/cobbler/watcher.py?%s_done=%s --output-document=kickstart_done"
+ def generate_kickstart_signal(self, obj, is_system=False, is_done=True):
+ doneness = "done"
+ if not is_done:
+ doneness = "start"
+ pattern = "wget http://%s/cobbler/watcher.py?%s_%s=%s -b"
if is_system:
- return pattern % (self.settings.server, "system", obj.name)
+ return pattern % (self.settings.server, "system", doneness, obj.name)
else:
- return pattern % (self.settings.server, "profile", obj.name)
+ return pattern % (self.settings.server, "profile", doneness, obj.name)
def generate_repo_stanza(self, profile):
# returns the line of repo additions (Anaconda supports in FC-6 and later) that adds
@@ -394,7 +398,8 @@ class BootSync:
))
meta["yum_repo_stanza"] = self.generate_repo_stanza(profile)
meta["yum_config_stanza"] = self.generate_config_stanza(profile)
- meta["kickstart_done"] = self.generate_kickstart_done(profile, is_system=True)
+ meta["kickstart_done"] = self.generate_kickstart_signal(profile, is_system=True, is_done=True)
+ meta["kickstart_start"] = self.generate_kickstart_signal(profile, is_system=True, is_done=False)
self.apply_template(kickstart_path, meta, dest)
except:
msg = "err_kickstart2"
diff --git a/cobbler/api.py b/cobbler/api.py
index ed2f66c..dda4052 100644
--- a/cobbler/api.py
+++ b/cobbler/api.py
@@ -21,6 +21,7 @@ import action_check
import action_enchant
import action_import
import action_reposync
+import action_status
import cexceptions
class BootAPI:
diff --git a/cobbler/cobbler.py b/cobbler/cobbler.py
index 62a0e4a..b2abfcd 100755
--- a/cobbler/cobbler.py
+++ b/cobbler/cobbler.py
@@ -18,6 +18,7 @@ import sys
import api
import os
import os.path
+import traceback
import cobbler_msg
import cexceptions
@@ -230,6 +231,8 @@ class BootCLI:
'cobbler status [--mode=text|somethingelse]'
"""
self.mode = "text"
+ if args is None or len(args) == 0:
+ return self.api.status(self.mode)
def set_mode(a):
if a.lower in [ "text" ]:
self.mode = a
@@ -237,12 +240,11 @@ class BootCLI:
else:
return False
commands = {
- '--mode' : lambda(a): set_mode(a)
+ '--mode' : set_mode
}
def go_status():
- return self.api.show_status(self.mode)
- on_ok = lambda: go_status()
- return self.apply_args(args, commands, on_ok)
+ return self.api.status(self.mode)
+ return self.apply_args(args, commands, go_status)
def enchant(self,args):
"""
@@ -499,6 +501,9 @@ def main():
except cexceptions.CobblerException, exc:
print str(exc)[1:-1] # remove framing air quotes
exitcode = 1
+ except Exception, other:
+ traceback.print_exc()
+ exitcode = 1
if LOCKING_ENABLED and not lock_hit:
try:
os.remove(LOCKFILE)