]> git.ipfire.org Git - people/shoehn/ipfire.org.git/blame - boot/boot.py
Show latest planet post on main page and add link for older annoucements.
[people/shoehn/ipfire.org.git] / boot / boot.py
CommitLineData
5470bdf1
MT
1#!/usr/bin/python
2
3import logging
4import os
5import tornado.httpserver
6import tornado.ioloop
7import tornado.locale
8import tornado.options
9import tornado.web
10
8b9b631e 11import backend
5470bdf1
MT
12
13BASEDIR = os.path.dirname(__file__)
14
a9bf3cbe 15def word_wrap(s, width=45):
7261a759
MT
16 paragraphs = s.split('\n')
17 lines = []
18 for paragraph in paragraphs:
19 while len(paragraph) > width:
20 pos = paragraph.rfind(' ', 0, width)
21 if not pos:
22 pos = width
23 lines.append(paragraph[:pos])
24 paragraph = paragraph[pos:]
a9bf3cbe 25 lines.append(paragraph.lstrip())
7261a759 26 return '\n'.join(lines)
5470bdf1
MT
27
28class BaseHandler(tornado.web.RequestHandler):
29 @property
30 def netboot(self):
31 return backend.NetBoot()
32
33
34class MenuGPXEHandler(BaseHandler):
35 """
36 menu.gpxe
37 """
38 def get(self):
39 # XXX Check if version of the bootloader is allright
40
41 # Devliver content
42 self.set_header("Content-Type", "text/plain")
43 self.write("#!gpxe\n")
44 self.write("chain menu.c32 premenu.cfg\n")
45
46
47class MenuCfgHandler(BaseHandler):
48 def _menu_string(self, menu, level=0):
49 s = ""
50
51 for entry in menu:
52 s += self._menu_entry(entry, level=level)
53
54 return s
55
56 def _menu_entry(self, entry, level=0):
57 lines = []
58
59 ident = "\t" * level
60
61 if entry.type == "seperator":
2109db85 62 lines.append(ident + "menu separator")
5470bdf1
MT
63
64 elif entry.type == "header":
65 lines.append(ident + "menu begin %d" % entry.id)
66 lines.append(ident + "\tmenu title %s" % entry.title)
67
68 # Add "Back..." entry
69 lines.append(ident + "\tlabel %d.back" % entry.id)
70 lines.append(ident + "\t\tmenu label Back...")
71 lines.append(ident + "\t\tmenu exit")
2109db85 72 lines.append(ident + "\tmenu separator")
5470bdf1 73
2109db85 74 lines.append("%s" % self._menu_string(entry.submenu, level=level+1))
5470bdf1 75 lines.append(ident + "menu end")
5470bdf1
MT
76
77 elif entry.type == "config":
78 lines.append(ident + "label %d" % entry.id)
79 lines.append(ident + "\tmenu label %s" % entry.title)
80 if entry.description:
81 lines.append(ident + "\ttext help")
7261a759 82 lines.append(word_wrap(entry.description))
5470bdf1
MT
83 lines.append(ident + "\tendtext")
84 lines.append(ident + "\tkernel /config/%s/boot.gpxe" % entry.item)
5470bdf1 85
7261a759 86 return "\n".join(lines + [""])
5470bdf1
MT
87
88 def get(self):
89 self.set_header("Content-Type", "text/plain")
90
91 menu = self._menu_string(self.netboot.get_menu(1))
92
93 self.render("menu.cfg", menu=menu)
94
95
96class BootGPXEHandler(BaseHandler):
97 def get(self, id):
98 config = self.netboot.get_config(id)
99 if not config:
100 raise tornado.web.HTTPError(404, "Configuration with ID '%s' was not found" % id)
101
102 lines = ["#!gpxe", "imgfree",]
103
104 line = "kernel -n img %s" % config.image1
105 if line.endswith(".iso"):
106 line += " iso"
8b9b631e
MT
107 if config.args:
108 line += " %s" % config.args
5470bdf1
MT
109 lines.append(line)
110
111 if config.image2:
112 lines.append("initrd -n img %s" % config.image2)
113
114 lines.append("boot img")
115
116 for line in lines:
117 self.write("%s\n" % line)
118
119
120class Application(tornado.web.Application):
121 def __init__(self):
122 settings = dict(
123 debug = True,
124 gzip = True,
8b9b631e
MT
125 static_path = os.path.join(BASEDIR, "static"),
126 template_path = os.path.join(BASEDIR, "templates"),
5470bdf1
MT
127 )
128
129 tornado.web.Application.__init__(self, **settings)
130
131 self.add_handlers(r"boot.ipfire.org", [
132 # Configurations
5fb24f31
MT
133 (r"/menu.gpxe", MenuGPXEHandler),
134 (r"/menu.cfg", MenuCfgHandler),
5470bdf1
MT
135 (r"/config/([0-9]+)/boot.gpxe", BootGPXEHandler),
136
137 # Static files
5fb24f31 138 (r"/(boot.png|custom.gpxe|premenu.cfg|vesamenu.c32|menu.c32)",
5470bdf1
MT
139 tornado.web.StaticFileHandler, { "path" : self.settings["static_path"] }),
140 ])
141
142 @property
143 def ioloop(self):
144 return tornado.ioloop.IOLoop.instance()
145
146 def shutdown(self, *args):
147 logging.debug("Caught shutdown signal")
148 self.ioloop.stop()
149
150 def run(self, port=8002):
151 logging.debug("Going to background")
152
153 # All requests should be done after 30 seconds or they will be killed.
154 self.ioloop.set_blocking_log_threshold(30)
155
156 http_server = tornado.httpserver.HTTPServer(self, xheaders=True)
157
158 # If we are not running in debug mode, we can actually run multiple
159 # frontends to get best performance out of our service.
160 if not self.settings["debug"]:
161 http_server.bind(port)
162 http_server.start(num_processes=4)
163 else:
164 http_server.listen(port)
165
166 self.ioloop.start()
167
168if __name__ == "__main__":
169 a = Application()
170
171 a.run()
172