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