summaryrefslogtreecommitdiffstats
path: root/cobbler/action_status.py
diff options
context:
space:
mode:
authorMichael DeHaan <mdehaan@mdehaan.rdu.redhat.com>2007-04-11 18:53:50 -0400
committerMichael DeHaan <mdehaan@mdehaan.rdu.redhat.com>2007-04-11 18:53:50 -0400
commitc3d1d703cdcbb911561c34f30f190067c641176f (patch)
tree3b4193133d9ff8d8d2e0b1cac3e9bb3307f7864a /cobbler/action_status.py
parent2e89faaf2853741579ed176baa761021311853a3 (diff)
downloadthird_party-cobbler-c3d1d703cdcbb911561c34f30f190067c641176f.tar.gz
third_party-cobbler-c3d1d703cdcbb911561c34f30f190067c641176f.tar.xz
third_party-cobbler-c3d1d703cdcbb911561c34f30f190067c641176f.zip
Kickstart tracking now mines the apache logs rather than relying on the
watcher.py mod_python script, so there is room for greater platform compatibility. A cgi-based more-portable alternative to watcher is still desirable. Since apache logs are cycled more frequently than cobbler logs, this does mean that we lose a bit of granularity with regards to start/stop times, though this can presumably be refined. Last request time (the most important bit) is still solid. Need to verify that Apache log time parsing (strptime) isn't doing anything strange with time zones as cobbler is logging GMT. I suspect it might and that would affect results and state detection.
Diffstat (limited to 'cobbler/action_status.py')
-rw-r--r--cobbler/action_status.py187
1 files changed, 113 insertions, 74 deletions
diff --git a/cobbler/action_status.py b/cobbler/action_status.py
index 09befef..b3e94a2 100644
--- a/cobbler/action_status.py
+++ b/cobbler/action_status.py
@@ -29,7 +29,72 @@ class BootStatusReport:
self.settings = config.settings()
self.mode = mode
- # -------------------------------------------------------
+ # -------------------------------------------------------
+
+ def scan_apache_logfiles(self):
+ results = {}
+ files = [ "/var/log/httpd/access_log" ]
+ for x in range(1,4):
+ consider = "/var/log/httpd/access_log.%s" % x
+ if os.path.exists(consider):
+ files.append(consider)
+ for fname in files:
+ fh = open(fname)
+ data = fh.readline()
+ while (data is not None and data != ""):
+ data = fh.readline()
+ #print data
+ tokens = data.split(None)
+ if len(tokens) < 6:
+ continue
+ #print "----"
+ ip = tokens[0]
+ stime = tokens[3].replace("[","")
+ req = tokens[6]
+ if req.find("/cblr") == -1:
+ continue
+ #print "%s,%s,%s,%s" % (tokens,ip,time,req)
+ ttime = time.strptime(stime,"%d/%b/%Y:%H:%M:%S")
+ #print ttime
+ itime = time.mktime(ttime)
+ if not results.has_key(ip):
+ results[ip] = {}
+ #print "ip (%s) time (%s) req (%s)" % (ip,itime,req)
+ results[ip][itime] = req
+
+ return results
+
+ # -------------------------------------------------------
+
+ def scan_syslog_logfiles(self):
+
+ # find all of the logged IP addrs
+ filelist = glob.glob("/var/log/cobbler/syslog/*")
+ filelist.sort()
+ results = {}
+
+ for fullname in filelist:
+ #fname = os.path.basename(fullname)
+ logfile = open(fullname, "r")
+ # for each line in the file...
+ data = logfile.readline()
+ while(data is not None and data != ""):
+ data = logfile.readline()
+
+ try:
+ (epoch, strdate, ip, request) = data.split("\t", 3)
+ epoch = float(epoch)
+ except:
+ continue
+
+ if not results.has_key(ip):
+ results[ip] = {}
+ # print "results (%s) (%s) <- %s" % (ip, epoch, request)
+ results[ip][epoch] = request
+
+ return results
+
+ # -------------------------------------------------------
def run(self):
"""
@@ -37,91 +102,56 @@ class BootStatusReport:
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.
"""
-
+
+ apache_results = self.scan_apache_logfiles()
+ syslog_results = self.scan_syslog_logfiles()
+ ips = apache_results.keys()
+ ips.sort()
+ ips2 = syslog_results.keys()
+ ips2.sort()
+
+ ips.extend(ips2)
+ ip_printed = {}
+
last_recorded_time = 0
time_collisions = 0
-
- # find all of the logged IP addrs
- filelist = glob.glob("/var/log/cobbler/syslog/*")
- filelist.sort()
header = ("Address", "State", "Started", "Last Request", "Seconds", "Log Entries")
print "%-20s | %-15s | %-25s | %-25s | %-10s | %-6s" % header
- for fullname in filelist:
- fname = os.path.basename(fullname) # access times log
- fullname2 = "/var/log/cobbler/kicklog/%s" % fname # remote syslog
-
+
+ for ip in ips:
+ if ip_printed.has_key(ip):
+ continue
+ ip_printed[ip] = 1
entries = {} # hash of access times and messages
- ip = None
-
- # both types of log files must be intertwingled (TM)
-
- for openme in [ fullname, fullname2 ]:
-
- # it's possible syslog never hit the server, that's ok.
- if not os.path.exists(openme):
- continue
-
- logfile = open(openme, "r")
- data = "..."
-
- # for each line in the file...
- while(data is not None and data != ""):
- data = logfile.readline()
-
- # fields are tab delimited
- # (1) seconds since 1970, in decimal
- # (2) ASCII date for humans
- # (3) IP address of requester
- # (4) HTTP request line
-
- try:
- (epoch, strdate, ip, request) = data.split("\t", 3)
- except:
- continue
-
- # 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
-
- # time collision voodoo
- # we are storing times in a hash, and this prevents them from colliding
- # which would break the filecount and possibly the state check
-
- logtime = float(epoch)
- if int(logtime) == last_recorded_time:
- time_collisions = time_collisions + 1
- else:
- time_collisions = 0
- logtime = logtime + (0.001 * time_collisions)
-
- # to make the report generation a bit easier, flag what we think are start/end points
-
+ if apache_results.has_key(ip):
+ times = apache_results[ip].keys()
+ for logtime in times:
+ request = apache_results[ip][logtime]
if request.find("?system_done") != -1:
- entries[logtime] = "DONE:%s" % request
+ entries[logtime] = "DONE"
elif request.find("?profile_done") != -1:
- entries[logtime] = "DONE:%s" % request
- elif request.find("methodcomplete") != -1:
- entries[logtime] = "DONE:%s" % request
- elif request.find("Method =") != -1:
- entries[logtime] = "START:%s" % request
+ entries[logtime] = "DONE"
else:
entries[logtime] = "1" # don't really care what the filename was
- last_recorded_time = int(logtime)
-
- # FIXME: calculate start times for each IP as defined as earliest file
- # requested after each stop time, or the first file requested if no
- # stop time.
-
- logfile.close()
+ if syslog_results.has_key(ip):
+ times = syslog_results[ip].keys()
+ for logtime in times:
+ request = syslog_results[ip][logtime]
+ if request.find("methodcomplete") != -1:
+ entries[logtime] = "DONE"
+ elif request.find("Method =") != -1:
+ entries[logtime] = "START"
+ else:
+ entries[logtime] = "1"
- # print the report line for this IP addr
self.generate_report(entries,ip)
+ # print entries
+
return True
#-----------------------------------------
@@ -142,23 +172,27 @@ class BootStatusReport:
last_done_time = 0
fcount = 0
+ if len(rtimes) == 0:
+ print "%s: ?" % ip
+ return
+
# for each request time the machine has made
for rtime in rtimes:
rtime = rtime
fname = entries[rtime]
- if fname.startswith("START:"):
+ if fname == "START":
install_state = "installing"
last_start_time = rtime
last_request_time = rtime
fcount = 0
- elif fname.startswith("DONE"):
+ elif fname == "DONE":
# kickstart finished
last_done_time = rtime
install_state = "done"
else:
- install_state = "installing"
+ install_state = "?"
last_request_time = rtime
fcount = fcount + 1
@@ -172,7 +206,12 @@ class BootStatusReport:
# FIXME: IP to MAC mapping where cobbler knows about it would be nice.
display_start = time.asctime(time.localtime(last_start_time))
display_last = time.asctime(time.localtime(last_request_time))
-
+
+ if display_start.find(" 1969") != -1:
+ display_start = "?"
+ elapsed_time = "?"
+
# print the status line for this IP address
print "%-20s | %-15s | %-25s | %-25s | %-10s | %-6s" % (ip, install_state, display_start, display_last, elapsed_time, fcount)
+