summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MANIFEST.in1
-rw-r--r--cobbler.spec2
-rw-r--r--cobbler/action_status.py187
-rw-r--r--cobbler/action_sync.py87
-rw-r--r--setup.py4
5 files changed, 117 insertions, 164 deletions
diff --git a/MANIFEST.in b/MANIFEST.in
index 650b088..445e623 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,6 +1,7 @@
include loaders/COPYING_ELILO
include loaders/elilo-3.6-ia64.efi
include loaders/menu.c32
+include templates/cobbler.conf
include templates/dhcp.template
include templates/pxeprofile.template
include templates/pxedefault.template
diff --git a/cobbler.spec b/cobbler.spec
index 08c3742..b50f616 100644
--- a/cobbler.spec
+++ b/cobbler.spec
@@ -79,7 +79,6 @@ test "x$RPM_BUILD_ROOT" != "x" && rm -rf $RPM_BUILD_ROOT
%dir /var/www/cobbler/profiles
%dir /var/www/cobbler/systems
%dir /var/www/cobbler/links
-/var/www/cobbler/watcher.py*
%defattr(-,root,root)
%dir /tftpboot/pxelinux.cfg
%dir /tftpboot/images
@@ -105,6 +104,7 @@ test "x$RPM_BUILD_ROOT" != "x" && rm -rf $RPM_BUILD_ROOT
/var/lib/cobbler/elilo-3.6-ia64.efi
/var/lib/cobbler/menu.c32
/etc/init.d/cobblersyslogd
+/etc/httpd/conf.d/cobbler.conf
%dir /var/log/cobbler/syslog
%doc AUTHORS CHANGELOG NEWS README COPYING
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)
+
diff --git a/cobbler/action_sync.py b/cobbler/action_sync.py
index d0efa06..2af7dd1 100644
--- a/cobbler/action_sync.py
+++ b/cobbler/action_sync.py
@@ -63,7 +63,6 @@ class BootSync:
self.clean_trees()
self.copy_koan()
self.copy_bootloaders()
- self.configure_httpd()
self.copy_distros()
self.validate_kickstarts()
self.build_trees()
@@ -167,92 +166,6 @@ class BootSync:
for x in metadata.keys():
template_data = template_data.replace("$%s" % x, metadata[x])
- def configure_httpd(self):
- """
- Create a config file to Apache that will allow access to the
- cobbler infrastructure available over TFTP over HTTP also.
- """
-
- conf_file = "/etc/httpd/conf.d/cobbler.conf"
-
- if not os.path.exists("/etc/httpd/conf.d"):
- print cobbler_msg.lookup("no_httpd")
- return
-
- # now we're going to figure out whether we actually need to write
- # the file. If the file exists and contains self.settings.webdir,
- # then we don't. and if the file is already there, then we really
- # don't have to restart the service either.
-
- found_webdir = False
- found_track_support = False
- if os.path.exists(conf_file):
- fh = open(conf_file, "r")
- data = fh.read()
- if data.find(self.settings.webdir) != -1:
- found_webdir = True
- if data.find("cblr") != -1:
- found_track_support = True
- fh.close()
-
- if found_track_support and found_webdir:
- # no http reconfig and restart needed
- return
-
- f = self.open_file(conf_file,"w+")
-
- # the watcher.py script appears a bit flakey in older Apache 2 versions
- # so only install the MP hook when we think Apache can handle it
- # otherwise the filter could corrupt some binary files (erg!) and the install
- # will die almost immediately. You've got to love all the corner cases in systems mgmt
- # software, don't you?
-
- release_info_fh = os.popen("rpm -q --whatprovides redhat-release")
- release_info = release_info_fh.read()
- release_info_fh.close()
-
- mod_python_ok = True
-
- for x in [ "redhat-release-5", "redhat-release-4", "redhat-release-3", "centos-release-4", "centos-release-3" ]:
- if release_info.lower().find(x) != -1:
- mod_python_ok = False
-
- if mod_python_ok:
- mp_section = """
- AddHandler mod_python .py
- PythonOutputFilter watcher WATCHER
- AddOutputFilter WATCHER ks.cfg
- AddOutputFilter WATCHER .rpm
- AddOutputFilter WATCHER .xml
- AddOutputFilter WATCHER .py
- PythonDebug On
- """
- else:
- mp_section = ""
-
- config_data = """
- #
- # This configuration file allows 'cobbler' boot info
- # to be accessed over HTTP in addition to PXE.
- AliasMatch ^/cobbler(/.*)?$ "/cobbler_webdir$1"
- AliasMatch ^/cobbler_track(/.*)?$ "/cobbler_webdir$1"
- AliasMatch ^/cblr(/.*)?$ "/cobbler_webdir$1"
- <Directory "/cobbler_webdir">
- Options Indexes FollowSymLinks
- AllowOverride None
- Order allow,deny
- Allow from all
- MPSECTION
- </Directory>
- """
- # this defaults to /var/www/cobbler if user didn't change it
- config_data = config_data.replace("/cobbler_webdir",self.settings.webdir)
- config_data = config_data.replace("MPSECTION", mp_section)
- self.tee(f, config_data)
- self.close_file(f)
-
- self.service("httpd", "reload")
-
def clean_trees(self):
"""
Delete any previously built pxelinux.cfg tree and virt tree info and then create
diff --git a/setup.py b/setup.py
index b949cd6..f46254e 100644
--- a/setup.py
+++ b/setup.py
@@ -15,6 +15,7 @@ if __name__ == "__main__":
manpath = "share/man/man1/"
cobpath = "/var/lib/cobbler/"
etcpath = "/etc/cobbler/"
+ wwwconf = "/etc/httpd/conf.d/"
wwwpath = "/var/www/cobbler/"
initpath = "/etc/init.d/"
logpath = "/var/log/cobbler/"
@@ -46,8 +47,7 @@ if __name__ == "__main__":
],
scripts = ["scripts/cobbler", "scripts/cobbler_syslogd"],
data_files = [
- # (docspath, ['README']),
- (wwwpath, ['scripts/watcher.py']),
+ (wwwconf, ['templates/cobbler.conf']),
(cobpath, ['loaders/elilo-3.6-ia64.efi']),
(cobpath, ['loaders/menu.c32']),
(etcpath, ['kickstarts/kickstart_fc5.ks']),