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
 
 {{ _("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() %}
 
 
        {% module NetBootMenuSeparator() %}
 
@@ -21,8 +21,9 @@ menu begin {{ release.sname }}
 {{ _("Install in text mode.") }}
                endtext
 
 {{ _("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
 
 {% if release.id >= 75 %}
        label {{ release.sname }}.scon
@@ -32,9 +33,9 @@ menu begin {{ release.sname }}
 {{ _("Install with serial console.") }}
                endtext
 
 {{ _("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() %}
 {% end %}
 
        {% module NetBootMenuSeparator() %}
@@ -43,3 +44,4 @@ menu begin {{ release.sname }}
                menu label {{ _("Back...") }}
                menu exit
 menu end
                menu label {{ _("Back...") }}
                menu exit
 menu end
+{% comment new line %}
index 192fe6f..90e2b96 100644 (file)
@@ -7,5 +7,5 @@ menu begin {{ id }}
 
        {% module NetBootMenuSeparator() %}
 
 
        {% 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
 menu end
index 3bd7d9f..98f0e83 100644 (file)
@@ -14,11 +14,29 @@ menu helpmsgrow 16
 menu background boot.png
 prompt 0
 
 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
   endtext
   menu label Graphical menu
   kernel vesamenu.c32
-  append menu.cfg
+  append menu.cfg?arch={{ arch }}&platform={{ platform }}
 
 label text
   menu label Text menu
 
 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
   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"/", 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"/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 }),
                ])
 
                                tornado.web.StaticFileHandler, { "path" : BOOT_STATIC_PATH }),
                ])
 
index 7184b22..48f7b5d 100644 (file)
@@ -365,17 +365,38 @@ class Release(Object):
                        if f:
                                f.close()
 
                        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
 
        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
 
                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
 
                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
        @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):
        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):
 
 
 class MenuGPXEHandler(BootBaseHandler):
@@ -58,8 +75,9 @@ class MenuGPXEHandler(BootBaseHandler):
                self.set_header("Content-Type", "text/plain")
                self.write("#!gpxe\n")
 
                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):
                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")
 
 
                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):
 
 class MenuCfgHandler(BootBaseHandler):
        class NightlyBuildReleaseDummy(object):
@@ -79,8 +103,20 @@ class MenuCfgHandler(BootBaseHandler):
                name = "Nightly Build"
                sname = "nightly-build"
 
                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
 
                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()
                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
 
                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,
                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):
 
 
 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):
 
 
 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,
                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):
 
 
 class NetBootMenuSeparatorModule(UIModule):