blob: e4516a8a6231f0c229de1c0230bd4c3a18ae1576 [file] [log] [blame]
Chris Sosa0356d3b2010-09-16 15:46:22 -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 Sosa0356d3b2010-09-16 15:46:22 -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 Sosa0356d3b2010-09-16 15:46:22 -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 Sosa0356d3b2010-09-16 15:46:22 -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 Sosa0356d3b2010-09-16 15:46:22 -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 Sosa0356d3b2010-09-16 15:46:22 -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 Sosa0356d3b2010-09-16 15:46:22 -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.')
Chris Sosa5d342a22010-09-28 16:54:41 -070096 parser.add_option('--use_cached', action="store_true", default=False,
97 help='Prefer cached image regardless of timestamps.')
Andrew de los Reyes52620802010-04-12 13:40:07 -070098 parser.add_option('--validate_factory_config', action="store_true",
99 dest='validate_factory_config',
100 help='Validate factory config file, then exit.')
Chris Sosa0356d3b2010-09-16 15:46:22 -0700101 # Clean up the args, due to httpserver's hardcoded use of sys.argv.
102 options, sys.argv = parser.parse_args(sys.argv)
rtc@google.com21a5ca32009-11-04 18:23:23 +0000103
Sean O'Connor14b6a0a2010-03-20 23:23:48 -0700104 root_dir = os.path.realpath('%s/../..' %
105 os.path.dirname(os.path.abspath(sys.argv[0])))
Chris Sosa0356d3b2010-09-16 15:46:22 -0700106
107 serve_only = False
108
Sean O'Connor14b6a0a2010-03-20 23:23:48 -0700109 if options.archive_dir:
110 static_dir = os.path.realpath(options.archive_dir)
Chris Sosa0356d3b2010-09-16 15:46:22 -0700111 _PrepareToServeUpdatesOnly(static_dir)
112 serve_only = True
Sean O'Connor14b6a0a2010-03-20 23:23:48 -0700113 else:
114 static_dir = os.path.realpath('%s/static' %
115 os.path.dirname(os.path.abspath(sys.argv[0])))
116 web.debug('dev root is %s' % root_dir)
117 os.system('mkdir -p %s' % static_dir)
Chris Sosa0356d3b2010-09-16 15:46:22 -0700118
119 web.debug('Serving from %s' % static_dir)
rtc@google.com21a5ca32009-11-04 18:23:23 +0000120
Andrew de los Reyes52620802010-04-12 13:40:07 -0700121 updater = autoupdate.Autoupdate(
122 root_dir=root_dir,
123 static_dir=static_dir,
Chris Sosa0356d3b2010-09-16 15:46:22 -0700124 serve_only=serve_only,
Andrew de los Reyes52620802010-04-12 13:40:07 -0700125 urlbase=options.urlbase,
126 test_image=options.test_image,
127 factory_config_path=options.factory_config,
Chris Sosa0356d3b2010-09-16 15:46:22 -0700128 client_prefix=options.client_prefix,
Chris Sosa5d342a22010-09-28 16:54:41 -0700129 forced_image=options.image,
130 use_cached=options.use_cached)
rtc@google.com64244662009-11-12 00:52:08 +0000131
Chris Sosa0356d3b2010-09-16 15:46:22 -0700132 if options.factory_config:
133 updater.ImportFactoryConfigFile(options.factory_config,
134 options.validate_factory_config)
135
136 if not options.validate_factory_config:
137 # We do not need to run the dev server for validating the factory config.
138 # TODO(nsanders): Write unit test to validate.
139 urls = ('/', 'index',
140 '/update', 'update',
141 '/update/(.+)', 'update',
142 '/build', 'build')
143
144 # Overrides the default WSGIServer routine -- see OverrideWSGIServer.
145 web.httpserver.WSGIServer = OverrideWSGIServer
146 app = web.application(urls, globals(), autoreload=True)
147 render = web.template.render('templates/')
148 app.run()