]>
Commit | Line | Data |
---|---|---|
5470bdf1 MT |
1 | #!/usr/bin/python |
2 | ||
3 | import logging | |
4 | import os | |
5 | import tornado.httpserver | |
6 | import tornado.ioloop | |
7 | import tornado.locale | |
8 | import tornado.options | |
9 | import tornado.web | |
10 | ||
8b9b631e | 11 | import backend |
5470bdf1 | 12 | |
9068dba1 MT |
13 | from handlers_base import BaseHandler |
14 | ||
5470bdf1 MT |
15 | BASEDIR = os.path.dirname(__file__) |
16 | ||
a9bf3cbe | 17 | def word_wrap(s, width=45): |
7261a759 MT |
18 | paragraphs = s.split('\n') |
19 | lines = [] | |
20 | for paragraph in paragraphs: | |
21 | while len(paragraph) > width: | |
22 | pos = paragraph.rfind(' ', 0, width) | |
23 | if not pos: | |
24 | pos = width | |
25 | lines.append(paragraph[:pos]) | |
26 | paragraph = paragraph[pos:] | |
a9bf3cbe | 27 | lines.append(paragraph.lstrip()) |
7261a759 | 28 | return '\n'.join(lines) |
5470bdf1 | 29 | |
9068dba1 | 30 | class BootBaseHandler(BaseHandler): |
37b5c0cf MT |
31 | @property |
32 | def arch(self): | |
33 | arch = self.get_argument("arch", "i386") | |
34 | if not arch in ("x86_64", "i586", "i386"): | |
35 | raise tornado.web.HTTPError(400, "Invalid architecture") | |
36 | ||
37 | if arch == "i386": | |
38 | arch = "i586" | |
39 | ||
40 | return arch | |
41 | ||
42 | @property | |
43 | def platform(self): | |
44 | platform = self.get_argument("platform", "pcbios") | |
45 | if not platform in ("pcbios", "efi"): | |
46 | raise tornado.web.HTTPError(400, "Invalid platform") | |
47 | ||
48 | return platform | |
5470bdf1 MT |
49 | |
50 | ||
8e2e1261 | 51 | class MenuGPXEHandler(BootBaseHandler): |
5470bdf1 MT |
52 | """ |
53 | menu.gpxe | |
54 | """ | |
55 | def get(self): | |
e847f85c MT |
56 | # Check if version of the bootloader is recent enough. |
57 | # Otherwise send the latest version of the PXE loader. | |
58 | user_agent = self.request.headers.get("User-Agent", None) | |
59 | if user_agent: | |
60 | try: | |
61 | client, version = user_agent.split("/") | |
62 | except: | |
63 | pass | |
64 | else: | |
65 | # We replaced gPXE by iPXE. | |
66 | if client == "gPXE": | |
67 | return self.serve_update() | |
68 | ||
69 | # Everything under version 1.0.0 should be | |
70 | # updated. | |
71 | if version < "1.0.0": | |
72 | return self.serve_update() | |
5470bdf1 | 73 | |
98133910 MT |
74 | # This is an outdated git build |
75 | if "c4bce" in version: | |
76 | return self.serve_update() | |
77 | ||
78 | # Deliver content | |
5470bdf1 MT |
79 | self.set_header("Content-Type", "text/plain") |
80 | self.write("#!gpxe\n") | |
e847f85c | 81 | |
37b5c0cf MT |
82 | self.write("set 209:string premenu.cfg?arch=%s&platform=%s\n" \ |
83 | % (self.arch, self.platform)) | |
e7c9ed3c | 84 | self.write("set 210:string http://boot.ipfire.org/\n") |
e847f85c MT |
85 | self.write("chain pxelinux.0\n") |
86 | ||
87 | def serve_update(self): | |
88 | self.set_header("Content-Type", "text/plain") | |
89 | self.write("#!gpxe\n") | |
90 | ||
91 | # Small warning | |
92 | self.write("echo\necho Your copy of gPXE/iPXE is too old. ") | |
93 | self.write("Upgrade to avoid seeing this every boot!\n") | |
94 | ||
95 | self.write("chain http://mirror0.ipfire.org/releases/ipfire-boot/latest/ipxe.kpxe\n") | |
5470bdf1 | 96 | |
98133910 | 97 | |
37b5c0cf MT |
98 | class PremenuCfgHandler(BootBaseHandler): |
99 | def get(self): | |
100 | self.set_header("Content-Type", "text/plain") | |
101 | ||
102 | self.render("netboot/premenu.cfg", arch=self.arch, platform=self.platform) | |
103 | ||
5470bdf1 | 104 | |
8e2e1261 | 105 | class MenuCfgHandler(BootBaseHandler): |
53211b33 MT |
106 | class NightlyBuildReleaseDummy(object): |
107 | id = 100 | |
108 | name = "Nightly Build" | |
109 | sname = "nightly-build" | |
110 | ||
37b5c0cf MT |
111 | def supports_arch(self, arch): |
112 | return arch in ("i586", "x86_64") | |
113 | ||
114 | def supports_platform(self, platform): | |
115 | return platform == "pcbios" | |
116 | ||
117 | def netboot_kernel_url(self, arch, platform): | |
118 | return "http://nightly.ipfire.org/next/latest/%s/images/vmlinuz" % arch | |
119 | ||
120 | def netboot_initrd_url(self, arch, platform): | |
121 | return "http://nightly.ipfire.org/next/latest/%s/images/instroot" % arch | |
122 | ||
123 | def netboot_args(self, arch, platform): | |
124 | return "installer.download-url=http://nightly.ipfire.org/next/latest/%s/images/installer.iso" % arch | |
53211b33 MT |
125 | |
126 | def is_netboot_capable(self): | |
127 | return True | |
128 | ||
129 | nightly_build = NightlyBuildReleaseDummy() | |
130 | ||
5470bdf1 MT |
131 | def get(self): |
132 | self.set_header("Content-Type", "text/plain") | |
133 | ||
9068dba1 | 134 | latest_release = self.releases.get_latest() |
37b5c0cf MT |
135 | if latest_release and not latest_release.supports_arch(self.arch): |
136 | latest_release = None | |
137 | ||
138 | stable_releases = [r for r in self.releases.get_stable() | |
139 | if r.supports_arch(self.arch) and r.supports_platform(self.platform)] | |
9068dba1 MT |
140 | try: |
141 | stable_releases.remove(latest_release) | |
142 | except ValueError: | |
143 | pass | |
144 | ||
37b5c0cf MT |
145 | development_releases = [r for r in self.releases.get_unstable() |
146 | if r.supports_arch(self.arch) and r.supports_platform(self.platform)] | |
53211b33 | 147 | development_releases.insert(0, self.nightly_build) |
5470bdf1 | 148 | |
9068dba1 | 149 | self.render("netboot/menu.cfg", latest_release=latest_release, |
37b5c0cf MT |
150 | stable_releases=stable_releases, development_releases=development_releases, |
151 | arch=self.arch, platform=self.platform) |