From 11caf6d738de018aa59bded94613dcf841600de2 Mon Sep 17 00:00:00 2001
From: Devan Goodwin <dgoodwin@rm-rf.ca>
Date: Fri, 8 Jan 2010 16:05:43 -0400
Subject: [PATCH] Support http URLs for distro kernel and initrd.

Appears this is only used for koan physical --replace-self provisioning,
guests seem to just resort to the install tree regardless of this
setting.

Koan was constructing a URL to fetch these anyhow, so no koan changes
were really required, it's fallback behavior results in just using the
URL anyhow.

If you do not try to specify http:// URLs for your distro's
kernel/initrd, this change should have no impact.
---
 cobbler/item_distro.py                 |   27 +++++++++++++-------
 cobbler/modules/install_post_report.py |    1 -
 cobbler/pxegen.py                      |   42 ++++++++++++++++++++++++-------
 cobbler/utils.py                       |   27 ++++++++++++++++++++
 koan/app.py                            |    2 +-
 5 files changed, 78 insertions(+), 21 deletions(-)

diff --git a/cobbler/item_distro.py b/cobbler/item_distro.py
index 1fe4dab..182352f 100644
--- a/cobbler/item_distro.py
+++ b/cobbler/item_distro.py
@@ -146,12 +146,12 @@ class Distro(item.Item):
 
     def set_kernel(self,kernel):
         """
-	Specifies a kernel.  The kernel parameter is a full path, a filename
-	in the configured kernel directory (set in /etc/cobbler.conf) or a
-	directory path that would contain a selectable kernel.  Kernel
-	naming conventions are checked, see docs in the utils module
-	for find_kernel.
-	"""
+        Specifies a kernel.  The kernel parameter is a full path, a filename
+        in the configured kernel directory (set in /etc/cobbler.conf) or a
+        directory path that would contain a selectable kernel.  Kernel
+        naming conventions are checked, see docs in the utils module
+        for find_kernel.
+        """
         if kernel is None or kernel == "":
             raise CX("kernel not specified")
         if utils.find_kernel(kernel):
@@ -227,8 +227,17 @@ class Distro(item.Item):
             raise CX("Error with distro %s - kernel is required" % (self.name))
         if self.initrd is None:
             raise CX("Error with distro %s - initrd is required" % (self.name))
-        if not os.path.exists(self.kernel):
-            raise CX("Error with distro %s - kernel path not found" % (self.name))
-        if not os.path.exists(self.initrd):
+
+        if utils.file_is_remote(self.kernel):
+            if not utils.remote_file_exists(self.kernel):
+                raise CX("Error with distro %s - kernel not found" % (self.name))
+        elif not os.path.exists(self.kernel):
+            raise CX("Error with distro %s - kernel not found" % (self.name))
+
+        if utils.file_is_remote(self.initrd):
+            if not utils.remote_file_exists(self.initrd):
+                raise CX("Error with distro %s - initrd path not found" % 
+                        (self.name))
+        elif not os.path.exists(self.initrd):
             raise CX("Error with distro %s - initrd path not found" % (self.name))
 
diff --git a/cobbler/modules/install_post_report.py b/cobbler/modules/install_post_report.py
index 3a41343..4d31e82 100755
--- a/cobbler/modules/install_post_report.py
+++ b/cobbler/modules/install_post_report.py
@@ -36,7 +36,6 @@ def run(api, args, logger):
 
     # go no further if this feature is turned off
     if not str(settings.build_reporting_enabled).lower() in [ "1", "yes", "y", "true"]:
-        print "not enabled"
         return 0
 
     objtype = args[0] # "target" or "profile"
diff --git a/cobbler/pxegen.py b/cobbler/pxegen.py
index 6f9e62d..6efbd68 100644
--- a/cobbler/pxegen.py
+++ b/cobbler/pxegen.py
@@ -150,20 +150,42 @@ class PXEGen:
             utils.mkdir(distro_dir)
             kernel = utils.find_kernel(d.kernel) # full path
             initrd = utils.find_initrd(d.initrd) # full path
-            if kernel is None or not os.path.isfile(kernel):
-                raise CX("kernel not found: %(file)s, distro: %(distro)s" % { "file" : d.kernel, "distro" : d.name })
-            if initrd is None or not os.path.isfile(initrd):
-                raise CX("initrd not found: %(file)s, distro: %(distro)s" % { "file" : d.initrd, "distro" : d.name })
-            b_kernel = os.path.basename(kernel)
-            b_initrd = os.path.basename(initrd)
+
+            if utils.file_is_remote(kernel):
+                if kernel is None:
+                    raise CX("kernel not found: %(file)s, distro: %(distro)s" % 
+                            { "file" : d.kernel, "distro" : d.name })
+            else:
+                if kernel is None or not os.path.isfile(kernel):
+                    raise CX("kernel not found: %(file)s, distro: %(distro)s" % 
+                            { "file" : d.kernel, "distro" : d.name })
+
+            if utils.file_is_remote(initrd):
+                if initrd is None:
+                    raise CX("initrd not found: %(file)s, distro: %(distro)s" % 
+                            { "file" : d.initrd, "distro" : d.name })
+            else:
+                if initrd is None or not os.path.isfile(initrd):
+                    raise CX("initrd not found: %(file)s, distro: %(distro)s" % 
+                            { "file" : d.initrd, "distro" : d.name })
+
             allow_symlink=False
             if dirtree == self.settings.webdir:
                 allow_symlink=True
-            dst1 = os.path.join(distro_dir, b_kernel)
-            dst2 = os.path.join(distro_dir, b_initrd)
-            utils.linkfile(kernel, dst1, symlink_ok=allow_symlink, api=self.api, logger=self.logger)
 
-            utils.linkfile(initrd, dst2, symlink_ok=allow_symlink, api=self.api, logger=self.logger)
+            # Kernels referenced by remote URL are passed through to koan directly,
+            # no need for copying the kernel locally:
+            if not utils.file_is_remote(kernel):
+                b_kernel = os.path.basename(kernel)
+                dst1 = os.path.join(distro_dir, b_kernel)
+                utils.linkfile(kernel, dst1, symlink_ok=allow_symlink, 
+                        api=self.api, logger=self.logger)
+
+            if not utils.file_is_remote(initrd):
+                b_initrd = os.path.basename(initrd)
+                dst2 = os.path.join(distro_dir, b_initrd)
+                utils.linkfile(initrd, dst2, symlink_ok=allow_symlink, 
+                        api=self.api, logger=self.logger)
 
     def copy_single_image_files(self, img):
         images_dir = os.path.join(self.bootloc, "images2")
diff --git a/cobbler/utils.py b/cobbler/utils.py
index 24ca4c6..50e0f19 100644
--- a/cobbler/utils.py
+++ b/cobbler/utils.py
@@ -352,6 +352,7 @@ def find_kernel(path):
     """
     if path is None:
         return None
+
     if os.path.isfile(path):
         #filename = os.path.basename(path)
         #if _re_kernel.match(filename):
@@ -359,8 +360,15 @@ def find_kernel(path):
         #elif filename == "vmlinuz":
         #   return path
         return path
+
     elif os.path.isdir(path):
         return find_highest_files(path,"vmlinuz",_re_kernel)
+
+    # For remote URLs we expect an absolute path, and will not
+    # do any searching for the latest:
+    elif file_is_remote(path) and remote_file_exists(path):
+        return path
+
     return None
 
 def remove_yum_olddata(path,logger=None):
@@ -390,6 +398,7 @@ def find_initrd(path):
     # FUTURE: try to match kernel/initrd pairs?
     if path is None:
         return None
+
     if os.path.isfile(path):
         #filename = os.path.basename(path)
         #if _re_initrd.match(filename):
@@ -397,8 +406,15 @@ def find_initrd(path):
         #if filename == "initrd.img" or filename == "initrd":
         #   return path
         return path
+
     elif os.path.isdir(path):
         return find_highest_files(path,"initrd.img",_re_initrd)
+
+    # For remote URLs we expect an absolute path, and will not
+    # do any searching for the latest:
+    elif file_is_remote(path) and remote_file_exists(path):
+        return path
+
     return None
 
 
@@ -469,6 +485,17 @@ def read_file_contents(file_location, logger=None, fetch_if_remote=False):
                 file_location))
 
 
+def remote_file_exists(file_url):
+    """ Return True if the remote file exists. """
+    try:
+        handler = urllib2.urlopen(file_url)
+        handler.close()
+        return True
+    except urllib2.HTTPError:
+        # File likely doesn't exist
+        return False
+
+
 def file_is_remote(file_location):
     """ 
     Returns true if the file is remote and referenced via a protocol
diff --git a/koan/app.py b/koan/app.py
index 1f08208..24e1582 100755
--- a/koan/app.py
+++ b/koan/app.py
@@ -1022,8 +1022,8 @@ class Koan:
             print "downloading initrd %s to %s" % (initrd_short, initrd_save)
             print "url=%s" % initrd
             utils.urlgrab(initrd,initrd_save)
-            print "downloading kernel %s to %s" % (kernel_short, kernel_save)
 
+            print "downloading kernel %s to %s" % (kernel_short, kernel_save)
             print "url=%s" % kernel
             utils.urlgrab(kernel,kernel_save)
         except:
-- 
1.6.5.2

