netboot: Allow booting multiple architectures
authorMichael Tremer <michael.tremer@ipfire.org>
Sat, 3 Oct 2015 15:22:37 +0000 (17:22 +0200)
committerMichael Tremer <michael.tremer@ipfire.org>
Sat, 3 Oct 2015 15:39:54 +0000 (17:39 +0200)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
templates/netboot/menu-config.cfg
templates/netboot/menu-header.cfg
templates/netboot/menu.cfg
templates/netboot/premenu.cfg [moved from static/netboot/premenu.cfg with 85% similarity]
webapp/__init__.py
webapp/backend/releases.py
webapp/handlers_boot.py
webapp/ui_modules.py

index 0f8450c..f064424 100644 (file)
@@ -8,9 +8,9 @@ menu begin {{ release.sname }}
 {{ _("Install %s...") % release.name }}
                endtext
 
-               kernel {{ release.netboot_kernel }}
-               initrd {{ release.netboot_initrd }}
-               append vga=791
+               kernel {{ release.netboot_kernel_url(arch, platform) }}
+               initrd {{ release.netboot_initrd_url(arch, platform) }}
+               append {{ release.netboot_args(arch, platform) }} vga=791
 
        {% module NetBootMenuSeparator() %}
 
@@ -21,8 +21,9 @@ menu begin {{ release.sname }}
 {{ _("Install in text mode.") }}
                endtext
 
-               kernel {{ release.netboot_kernel }}
-               initrd {{ release.netboot_initrd }}
+               kernel {{ release.netboot_kernel_url(arch, platform) }}
+               initrd {{ release.netboot_initrd_url(arch, platform) }}
+               {% if release.netboot_args(arch, platform) %}append {{ release.netboot_args(arch, platform) }}{% end %}
 
 {% if release.id >= 75 %}
        label {{ release.sname }}.scon
@@ -32,9 +33,9 @@ menu begin {{ release.sname }}
 {{ _("Install with serial console.") }}
                endtext
 
-               kernel {{ release.netboot_kernel }}
-               initrd {{ release.netboot_initrd }}
-               append console=ttyS0,115200 novga
+               kernel {{ release.netboot_kernel_url(arch, platform) }}
+               initrd {{ release.netboot_initrd_url(arch, platform) }}
+               append {{ release.netboot_args(arch, platform) }} console=ttyS0,115200 novga
 {% end %}
 
        {% module NetBootMenuSeparator() %}
@@ -43,3 +44,4 @@ menu begin {{ release.sname }}
                menu label {{ _("Back...") }}
                menu exit
 menu end
+{% comment new line %}
index 192fe6f..90e2b96 100644 (file)
@@ -7,5 +7,5 @@ menu begin {{ id }}
 
        {% module NetBootMenuSeparator() %}
 
-       {% for r in [r for r in releases if r.is_netboot_capable()] %}{% module NetBootMenuConfig(r) %}{% end %}
+       {% for r in [r for r in releases if r.is_netboot_capable()] %}{% module NetBootMenuConfig(r, arch=arch, platform=platform) %}{% end %}
 menu end
index 3bd7d9f..98f0e83 100644 (file)
@@ -14,11 +14,29 @@ menu helpmsgrow 16
 menu background boot.png
 prompt 0
 
-menu title {{ _("IPFire boot menu") }}
+menu title {{ _("IPFire boot menu") }} ({{ arch }})
 
-{% module NetBootMenuConfig(latest_release) %}
+{% if latest_release %}
+       {% module NetBootMenuConfig(latest_release, arch=arch, platform=platform) %}
+       {% module NetBootMenuSeparator() %}
+{% end %}
 
-{% module NetBootMenuSeparator() %}
+{% if stable_releases %}
+       {% module NetBootMenuHeader(_("Stable releases"), stable_releases, arch=arch, platform=platform) %}
+{% end %}
 
-{% module NetBootMenuHeader(_("Stable releases"), stable_releases) %}
-{% module NetBootMenuHeader(_("Development releases"), development_releases) %}
+{% if development_releases %}
+       {% module NetBootMenuHeader(_("Development releases"), development_releases, arch=arch, platform=platform) %}
+{% end %}
+
+{% if arch == "x86_64" %}
+       menu separator
+
+       label change.to.i586
+               text help
+{{ _("You can as well install a 32-bit version of IPFire") }}
+               endtext
+               menu label {{ _("Change to i586") }}
+               kernel vesamenu.c32
+               append premenu.cfg?arch=i586&platform={{ platform }}
+{% end %}
similarity index 85%
rename from static/netboot/premenu.cfg
rename to templates/netboot/premenu.cfg
index 339d7a4..c207a84 100644 (file)
@@ -26,7 +26,7 @@ label vesa
   endtext
   menu label Graphical menu
   kernel vesamenu.c32
-  append menu.cfg
+  append menu.cfg?arch={{ arch }}&platform={{ platform }}
 
 label text
   menu label Text menu
@@ -34,4 +34,4 @@ label text
   Use this menu if the graphical menu does not work on your system.
   endtext
   kernel menu.c32
-  append menu.cfg
+  append menu.cfg?arch={{ arch }}&platform={{ platform }}
index eb31d1d..a6d380b 100644 (file)
@@ -218,11 +218,12 @@ class Application(tornado.web.Application):
                        (r"/", tornado.web.RedirectHandler, { "url" : "http://www.ipfire.org/download" }),
 
                        # Configurations
+                       (r"/premenu.cfg", PremenuCfgHandler),
                        (r"/menu.gpxe", MenuGPXEHandler),
                        (r"/menu.cfg", MenuCfgHandler),
 
                        # Static files
-                       (r"/(boot\.png|premenu\.cfg|pxelinux\.0|menu\.c32|vesamenu\.c32)",
+                       (r"/(boot\.png|pxelinux\.0|menu\.c32|vesamenu\.c32)",
                                tornado.web.StaticFileHandler, { "path" : BOOT_STATIC_PATH }),
                ])
 
index 7184b22..48f7b5d 100644 (file)
@@ -365,17 +365,38 @@ class Release(Object):
                        if f:
                                f.close()
 
+       def supports_arch(self, arch):
+               # Currently there is nothing else than i586 supported
+               if arch == "i586":
+                       return True
+
+               return False
+
+       def supports_platform(self, platform):
+               # Currently there is nothing else than pcbios supported
+               if platform == "pcbios":
+                       return True
+
+               return False
+
        def is_netboot_capable(self):
                return self.path and "ipfire-2.x" in self.path
 
-       @property
-       def netboot_kernel(self):
+       def netboot_kernel_url(self, arch, platform):
+               assert self.supports_arch(arch)
+               assert self.supports_platform(platform)
+
                return "http://downloads.ipfire.org/%s/images/vmlinuz" % self.path
 
-       @property
-       def netboot_initrd(self):
+       def netboot_initrd_url(self, arch, platform):
+               assert self.supports_arch(arch)
+               assert self.supports_platform(platform)
+
                return "http://downloads.ipfire.org/%s/images/instroot" % self.path
 
+       def netboot_args(self, arch, platform):
+               return ""
+
        @property
        def news_id(self):
                return self.__data.news_id
index 6fed8dd..bccf586 100644 (file)
@@ -28,7 +28,24 @@ def word_wrap(s, width=45):
        return '\n'.join(lines)
 
 class BootBaseHandler(BaseHandler):
-       pass
+       @property
+       def arch(self):
+               arch = self.get_argument("arch", "i386")
+               if not arch in ("x86_64", "i586", "i386"):
+                       raise tornado.web.HTTPError(400, "Invalid architecture")
+
+               if arch == "i386":
+                       arch = "i586"
+
+               return arch
+
+       @property
+       def platform(self):
+               platform = self.get_argument("platform", "pcbios")
+               if not platform in ("pcbios", "efi"):
+                       raise tornado.web.HTTPError(400, "Invalid platform")
+
+               return platform
 
 
 class MenuGPXEHandler(BootBaseHandler):
@@ -58,8 +75,9 @@ class MenuGPXEHandler(BootBaseHandler):
                self.set_header("Content-Type", "text/plain")
                self.write("#!gpxe\n")
 
-               self.write("set 209:string premenu.cfg\n")
-               self.write("set 210:string http://boot.ipfire.org/\n")
+               self.write("set 209:string premenu.cfg?arch=%s&platform=%s\n" \
+                       % (self.arch, self.platform))
+               self.write("set 210:string http://boot.dev.ipfire.org/\n")
                self.write("chain pxelinux.0\n")
 
        def serve_update(self):
@@ -72,6 +90,12 @@ class MenuGPXEHandler(BootBaseHandler):
 
                self.write("chain http://mirror0.ipfire.org/releases/ipfire-boot/latest/ipxe.kpxe\n")
 
+class PremenuCfgHandler(BootBaseHandler):
+       def get(self):
+               self.set_header("Content-Type", "text/plain")
+
+               self.render("netboot/premenu.cfg", arch=self.arch, platform=self.platform)
+
 
 class MenuCfgHandler(BootBaseHandler):
        class NightlyBuildReleaseDummy(object):
@@ -79,8 +103,20 @@ class MenuCfgHandler(BootBaseHandler):
                name = "Nightly Build"
                sname = "nightly-build"
 
-               netboot_kernel = "http://nightly.ipfire.org/next/latest/i586/images/vmlinuz"
-               netboot_initrd = "http://nightly.ipfire.org/next/latest/i586/images/instroot"
+               def supports_arch(self, arch):
+                       return arch in ("i586", "x86_64")
+
+               def supports_platform(self, platform):
+                       return platform == "pcbios"
+
+               def netboot_kernel_url(self, arch, platform):
+                       return "http://nightly.ipfire.org/next/latest/%s/images/vmlinuz" % arch
+
+               def netboot_initrd_url(self, arch, platform):
+                       return "http://nightly.ipfire.org/next/latest/%s/images/instroot" % arch
+
+               def netboot_args(self, arch, platform):
+                       return "installer.download-url=http://nightly.ipfire.org/next/latest/%s/images/installer.iso" % arch
 
                def is_netboot_capable(self):
                        return True
@@ -91,14 +127,20 @@ class MenuCfgHandler(BootBaseHandler):
                self.set_header("Content-Type", "text/plain")
 
                latest_release = self.releases.get_latest()
-               stable_releases = self.releases.get_stable()
+               if latest_release and not latest_release.supports_arch(self.arch):
+                       latest_release = None
+
+               stable_releases = [r for r in self.releases.get_stable()
+                       if r.supports_arch(self.arch) and r.supports_platform(self.platform)]
                try:
                        stable_releases.remove(latest_release)
                except ValueError:
                        pass
 
-               development_releases = self.releases.get_unstable()
+               development_releases = [r for r in self.releases.get_unstable()
+                       if r.supports_arch(self.arch) and r.supports_platform(self.platform)]
                development_releases.insert(0, self.nightly_build)
 
                self.render("netboot/menu.cfg", latest_release=latest_release,
-                       stable_releases=stable_releases, development_releases=development_releases)
+                       stable_releases=stable_releases, development_releases=development_releases,
+                       arch=self.arch, platform=self.platform)
index fa29edb..514688f 100644 (file)
@@ -178,18 +178,19 @@ class MirrorsTableModule(UIModule):
 
 
 class NetBootMenuConfigModule(UIModule):
-       def render(self, release):
-               return self.render_string("netboot/menu-config.cfg", release=release)
+       def render(self, release, arch=None, platform=None):
+               return self.render_string("netboot/menu-config.cfg", release=release,
+                       arch=arch, platform=platform)
 
 
 class NetBootMenuHeaderModule(UIModule):
-       def render(self, title, releases):
+       def render(self, title, releases, arch=None, platform=None):
                id = unicodedata.normalize("NFKD", unicode(title)).encode("ascii", "ignore")
                id = re.sub(r"[^\w]+", " ", id)
                id = "-".join(id.lower().strip().split())
 
                return self.render_string("netboot/menu-header.cfg", id=id,
-                       title=title, releases=releases)
+                       title=title, releases=releases, arch=arch, platform=platform)
 
 
 class NetBootMenuSeparatorModule(UIModule):