blob: 2af67068df343fc3d1c7939811cfd0d48f807963 [file] [log] [blame]
Chris Sosaaae36452010-09-15 17:06:05 -07001# Copyright (c) 2009-2010 The Chromium OS Authors. All rights reserved.
rtc@google.comded22402009-10-26 22:36:21 +00002# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
Sean O'Connor14b6a0a2010-03-20 23:23:48 -07005import optparse
rtc@google.comded22402009-10-26 22:36:21 +00006import os
chocobo@google.com4dc25812009-10-27 23:46:26 +00007import sys
Andrew de los Reyes52620802010-04-12 13:40:07 -07008import web
rtc@google.comded22402009-10-26 22:36:21 +00009
Chris Sosaaae36452010-09-15 17:06:05 -070010import autoupdate
11import buildutil
12
13# Sets up global to share between classes.
rtc@google.com21a5ca32009-11-04 18:23:23 +000014global updater
15updater = None
rtc@google.comded22402009-10-26 22:36:21 +000016
rtc@google.com64244662009-11-12 00:52:08 +000017
rtc@google.comded22402009-10-26 22:36:21 +000018class index:
19 def GET(self):
Tan Gaoba175362010-07-07 11:25:12 -070020 return render.index(None)
rtc@google.comded22402009-10-26 22:36:21 +000021
Chris Sosaaae36452010-09-15 17:06:05 -070022
rtc@google.comded22402009-10-26 22:36:21 +000023class update:
24 """
Tan Gaoba175362010-07-07 11:25:12 -070025 Processes updates from the client machine. If an update is found, the url
rtc@google.comded22402009-10-26 22:36:21 +000026 references a static link that can be served automagically from web.py.
27 """
Sean O'Connor14b6a0a2010-03-20 23:23:48 -070028 def POST(self, args=None):
29 return updater.HandleUpdatePing(web.data(), args)
rtc@google.com21a5ca32009-11-04 18:23:23 +000030
Chris Sosaaae36452010-09-15 17:06:05 -070031
rtc@google.com64244662009-11-12 00:52:08 +000032class build:
33 """
34 builds the package specified by the pkg parameter and returns the name
35 of the output file.
36 """
Ryan Cairnsdd1ceb82010-03-02 21:35:01 -080037 def POST(self):
rtc@google.com64244662009-11-12 00:52:08 +000038 input = web.input()
Sean O'Connor14b6a0a2010-03-20 23:23:48 -070039 web.debug('emerging %s ' % input.pkg)
40 emerge_command = 'emerge-%s %s' % (input.board, input.pkg)
Ryan Cairnsdd1ceb82010-03-02 21:35:01 -080041 err = os.system(emerge_command)
42 if err != 0:
Sean O'Connor14b6a0a2010-03-20 23:23:48 -070043 raise Exception('failed to execute %s' % emerge_command)
Mandeep Singh Bainesea6b7a52010-08-17 14:03:57 -070044 eclean_command = 'eclean-%s -d packages' % input.board
45 err = os.system(eclean_command)
46 if err != 0:
47 raise Exception('failed to execute %s' % emerge_command)
rtc@google.comded22402009-10-26 22:36:21 +000048
Chris Sosaaae36452010-09-15 17:06:05 -070049
Darin Petkove17164a2010-08-11 13:24:41 -070050def OverrideWSGIServer(server_address, wsgi_app):
51 """Creates a CherryPyWSGIServer instance.
52
53 Overrides web.py's WSGIServer routine (web.httpserver.WSGIServer) to
54 increase the accepted connection socket timeout from the default 10
55 seconds to 10 minutes. The extra time is necessary to serve delta
56 updates as well as update requests from a low priority update_engine
57 process running on a heavily loaded Chrome OS device.
58 """
59 web.debug('using local OverrideWSGIServer routine')
60 from web.wsgiserver import CherryPyWSGIServer
61 return CherryPyWSGIServer(server_address, wsgi_app, server_name="localhost",
62 timeout=600)
63
Chris Sosaaae36452010-09-15 17:06:05 -070064def _PrepareToServeUpdatesOnly(image_dir):
65 """Sets up symlink to image_dir for serving purposes."""
66 assert os.path.exists(image_dir), '%s must exist.' % image_dir
67 # If we're serving out of an archived build dir (e.g. a
68 # buildbot), prepare this webserver's magic 'static/' dir with a
69 # link to the build archive.
70 web.debug('Preparing autoupdate for "serve updates only" mode.')
71 if os.path.exists('static/archive'):
72 if image_dir != os.readlink('static/archive'):
73 web.debug('removing stale symlink to %s' % image_dir)
74 os.unlink('static/archive')
75 os.symlink(image_dir, 'static/archive')
76 else:
77 os.symlink(image_dir, 'static/archive')
78 web.debug('archive dir: %s ready to be used to serve images.' % image_dir)
79
80
Sean O'Connor14b6a0a2010-03-20 23:23:48 -070081if __name__ == '__main__':
82 usage = 'usage: %prog [options]'
83 parser = optparse.OptionParser(usage)
Sean O'Connore38ea152010-04-16 13:50:40 -070084 parser.add_option('--archive_dir', dest='archive_dir',
Sean O'Connor14b6a0a2010-03-20 23:23:48 -070085 help='serve archived builds only.')
Andrew de los Reyes9223f132010-05-07 17:08:17 -070086 parser.add_option('--client_prefix', dest='client_prefix',
87 help='Required prefix for client software version.',
88 default='MementoSoftwareUpdate')
Andrew de los Reyes52620802010-04-12 13:40:07 -070089 parser.add_option('--factory_config', dest='factory_config',
90 help='Config file for serving images from factory floor.')
Chris Sosaaae36452010-09-15 17:06:05 -070091 parser.add_option('--image', dest='image',
92 help='Force update using this image.')
Sean O'Connor1f7fd362010-04-07 16:34:52 -070093 parser.add_option('-t', action='store_true', dest='test_image')
94 parser.add_option('-u', '--urlbase', dest='urlbase',
95 help='base URL, other than devserver, for update images.')
Andrew de los Reyes52620802010-04-12 13:40:07 -070096 parser.add_option('--validate_factory_config', action="store_true",
97 dest='validate_factory_config',
98 help='Validate factory config file, then exit.')
Chris Sosaaae36452010-09-15 17:06:05 -070099 # Clean up the args, due to httpserver's hardcoded use of sys.argv.
100 options, sys.argv = parser.parse_args(sys.argv)
rtc@google.com21a5ca32009-11-04 18:23:23 +0000101
Sean O'Connor14b6a0a2010-03-20 23:23:48 -0700102 root_dir = os.path.realpath('%s/../..' %
103 os.path.dirname(os.path.abspath(sys.argv[0])))
Chris Sosaaae36452010-09-15 17:06:05 -0700104
105 serve_only = False
106
Sean O'Connor14b6a0a2010-03-20 23:23:48 -0700107 if options.archive_dir:
108 static_dir = os.path.realpath(options.archive_dir)
Chris Sosaaae36452010-09-15 17:06:05 -0700109 _PrepareToServeUpdatesOnly(static_dir)
110 serve_only = True
Sean O'Connor14b6a0a2010-03-20 23:23:48 -0700111 else:
112 static_dir = os.path.realpath('%s/static' %
113 os.path.dirname(os.path.abspath(sys.argv[0])))
114 web.debug('dev root is %s' % root_dir)
115 os.system('mkdir -p %s' % static_dir)
Chris Sosaaae36452010-09-15 17:06:05 -0700116
117 web.debug('Serving from %s' % static_dir)
rtc@google.com21a5ca32009-11-04 18:23:23 +0000118
Andrew de los Reyes52620802010-04-12 13:40:07 -0700119 updater = autoupdate.Autoupdate(
120 root_dir=root_dir,
121 static_dir=static_dir,
Chris Sosaaae36452010-09-15 17:06:05 -0700122 serve_only=serve_only,
Andrew de los Reyes52620802010-04-12 13:40:07 -0700123 urlbase=options.urlbase,
124 test_image=options.test_image,
125 factory_config_path=options.factory_config,
Chris Sosaaae36452010-09-15 17:06:05 -0700126 client_prefix=options.client_prefix,
127 forced_image=options.image)
rtc@google.com64244662009-11-12 00:52:08 +0000128
Chris Sosaaae36452010-09-15 17:06:05 -0700129 if options.factory_config:
130 updater.ImportFactoryConfigFile(factory_config_path,
131 validate_factory_config)
132
133 if not options.validate_factory_config:
134 # We do not need to run the dev server for validating the factory config.
135 # TODO(nsanders): Write unit test to validate.
136 urls = ('/', 'index',
137 '/update', 'update',
138 '/update/(.+)', 'update',
139 '/build', 'build')
140
141 # Overrides the default WSGIServer routine -- see OverrideWSGIServer.
142 web.httpserver.WSGIServer = OverrideWSGIServer
143 app = web.application(urls, globals(), autoreload=True)
144 render = web.template.render('templates/')
145 app.run()