]>
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 MT |
73 | |
74 | # Devliver content | |
75 | self.set_header("Content-Type", "text/plain") | |
76 | self.write("#!gpxe\n") | |
e847f85c | 77 | |
37b5c0cf MT |
78 | self.write("set 209:string premenu.cfg?arch=%s&platform=%s\n" \ |
79 | % (self.arch, self.platform)) | |
80 | self.write("set 210:string http://boot.dev.ipfire.org/\n") | |
e847f85c MT |
81 | self.write("chain pxelinux.0\n") |
82 | ||
83 | def serve_update(self): | |
84 | self.set_header("Content-Type", "text/plain") | |
85 | self.write("#!gpxe\n") | |
86 | ||
87 | # Small warning | |
88 | self.write("echo\necho Your copy of gPXE/iPXE is too old. ") | |
89 | self.write("Upgrade to avoid seeing this every boot!\n") | |
90 | ||
91 | self.write("chain http://mirror0.ipfire.org/releases/ipfire-boot/latest/ipxe.kpxe\n") | |
5470bdf1 | 92 | |
37b5c0cf MT |
93 | class PremenuCfgHandler(BootBaseHandler): |
94 | def get(self): | |
95 | self.set_header("Content-Type", "text/plain") | |
96 | ||
97 | self.render("netboot/premenu.cfg", arch=self.arch, platform=self.platform) | |
98 | ||
5470bdf1 | 99 | |
8e2e1261 | 100 | class MenuCfgHandler(BootBaseHandler): |
53211b33 MT |
101 | class NightlyBuildReleaseDummy(object): |
102 | id = 100 | |
103 | name = "Nightly Build" | |
104 | sname = "nightly-build" | |
105 | ||
37b5c0cf MT |
106 | def supports_arch(self, arch): |
107 | return arch in ("i586", "x86_64") | |
108 | ||
109 | def supports_platform(self, platform): | |
110 | return platform == "pcbios" | |
111 | ||
112 | def netboot_kernel_url(self, arch, platform): | |
113 | return "http://nightly.ipfire.org/next/latest/%s/images/vmlinuz" % arch | |
114 | ||
115 | def netboot_initrd_url(self, arch, platform): | |
116 | return "http://nightly.ipfire.org/next/latest/%s/images/instroot" % arch | |
117 | ||
118 | def netboot_args(self, arch, platform): | |
119 | return "installer.download-url=http://nightly.ipfire.org/next/latest/%s/images/installer.iso" % arch | |
53211b33 MT |
120 | |
121 | def is_netboot_capable(self): | |
122 | return True | |
123 | ||
124 | nightly_build = NightlyBuildReleaseDummy() | |
125 | ||
5470bdf1 MT |
126 | def get(self): |
127 | self.set_header("Content-Type", "text/plain") | |
128 | ||
9068dba1 | 129 | latest_release = self.releases.get_latest() |
37b5c0cf MT |
130 | if latest_release and not latest_release.supports_arch(self.arch): |
131 | latest_release = None | |
132 | ||
133 | stable_releases = [r for r in self.releases.get_stable() | |
134 | if r.supports_arch(self.arch) and r.supports_platform(self.platform)] | |
9068dba1 MT |
135 | try: |
136 | stable_releases.remove(latest_release) | |
137 | except ValueError: | |
138 | pass | |
139 | ||
37b5c0cf MT |
140 | development_releases = [r for r in self.releases.get_unstable() |
141 | if r.supports_arch(self.arch) and r.supports_platform(self.platform)] | |
53211b33 | 142 | development_releases.insert(0, self.nightly_build) |
5470bdf1 | 143 | |
9068dba1 | 144 | self.render("netboot/menu.cfg", latest_release=latest_release, |
37b5c0cf MT |
145 | stable_releases=stable_releases, development_releases=development_releases, |
146 | arch=self.arch, platform=self.platform) |