Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(258)

Side by Side Diff: src/platform/dev/autoupdate.py

Issue 1774021: Modifies dev server to produce stateful gzip and modify image_to_live to use it. (Closed) Base URL: ssh://git@chromiumos-git//chromeos
Patch Set: Fixes for seano Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/platform/dev/stateful_update.sh » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright (c) 2009 The Chromium OS Authors. All rights reserved. 1 # Copyright (c) 2009 The Chromium OS Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 from buildutil import BuildObject 5 from buildutil import BuildObject
6 from xml.dom import minidom 6 from xml.dom import minidom
7 7
8 import os 8 import os
9 import shutil 9 import shutil
10 import sys 10 import sys
11 import web 11 import web
12 12
13 class Autoupdate(BuildObject): 13 class Autoupdate(BuildObject):
14 # Basic functionality of handling ChromeOS autoupdate pings 14 # Basic functionality of handling ChromeOS autoupdate pings
15 # and building/serving update images. 15 # and building/serving update images.
16 # TODO(rtc): Clean this code up and write some tests. 16 # TODO(rtc): Clean this code up and write some tests.
17 17
18 def __init__(self, serve_only=None, test_image=False, urlbase=None, 18 def __init__(self, serve_only=None, test_image=False, urlbase=None,
19 factory_config_path=None, validate_factory_config=None, 19 factory_config_path=None, validate_factory_config=None,
20 *args, **kwargs): 20 *args, **kwargs):
21 super(Autoupdate, self).__init__(*args, **kwargs) 21 super(Autoupdate, self).__init__(*args, **kwargs)
22 self.serve_only = serve_only 22 self.serve_only = serve_only
23 self.test_image=test_image 23 self.test_image = test_image
24 self.static_urlbase = urlbase 24 self.static_urlbase = urlbase
25 if serve_only: 25 if serve_only:
26 # If we're serving out of an archived build dir (e.g. a 26 # If we're serving out of an archived build dir (e.g. a
27 # buildbot), prepare this webserver's magic 'static/' dir with a 27 # buildbot), prepare this webserver's magic 'static/' dir with a
28 # link to the build archive. 28 # link to the build archive.
29 web.debug('Autoupdate in "serve update images only" mode.') 29 web.debug('Autoupdate in "serve update images only" mode.')
30 if os.path.exists('static/archive'): 30 if os.path.exists('static/archive'):
31 archive_symlink = os.readlink('static/archive') 31 archive_symlink = os.readlink('static/archive')
32 if archive_symlink != self.static_dir: 32 if archive_symlink != self.static_dir:
33 web.debug('removing stale symlink to %s' % self.static_dir) 33 web.debug('removing stale symlink to %s' % self.static_dir)
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 return latest_version.split('-')[0] 77 return latest_version.split('-')[0]
78 78
79 def CanUpdate(self, client_version, latest_version): 79 def CanUpdate(self, client_version, latest_version):
80 """ 80 """
81 Returns true iff the latest_version is greater than the client_version. 81 Returns true iff the latest_version is greater than the client_version.
82 """ 82 """
83 client_tokens = client_version.split('.') 83 client_tokens = client_version.split('.')
84 latest_tokens = latest_version.split('.') 84 latest_tokens = latest_version.split('.')
85 web.debug('client version %s latest version %s' \ 85 web.debug('client version %s latest version %s' \
86 % (client_version, latest_version)) 86 % (client_version, latest_version))
87 for i in range(0,4): 87 for i in range(4):
88 if int(latest_tokens[i]) == int(client_tokens[i]): 88 if int(latest_tokens[i]) == int(client_tokens[i]):
89 continue 89 continue
90 return int(latest_tokens[i]) > int(client_tokens[i]) 90 return int(latest_tokens[i]) > int(client_tokens[i])
91 return False 91 return False
92 92
93 def UnpackImage(self, image_path, kernel_file, rootfs_file): 93 def UnpackImage(self, image_path, image_file, stateful_file, kernel_file, root fs_file):
94 if os.path.exists(rootfs_file) and os.path.exists(kernel_file): 94 unpack_command = 'cd %s && ./unpack_partitions.sh %s' % \
95 (image_path, image_file)
96 if os.system(unpack_command) == 0:
97 shutil.move(os.path.join(image_path, 'part_1'), stateful_file)
98 shutil.move(os.path.join(image_path, 'part_2'), kernel_file)
99 shutil.move(os.path.join(image_path, 'part_3'), rootfs_file)
100 os.system('cd %s && rm part_*' % image_path)
95 return True 101 return True
102 return False
103
104 def UnpackZip(self, image_path, image_file):
105 return os.system('cd %s && unzip -o image.zip %s unpack_partitions.sh' % \
106 (image_path, image_file)) == 0
107
108 def GetImageBinPath(self, image_path):
96 if self.test_image: 109 if self.test_image:
97 image_file = 'chromiumos_test_image.bin' 110 image_file = 'chromiumos_test_image.bin'
98 else: 111 else:
99 image_file = 'chromiumos_image.bin' 112 image_file = 'chromiumos_image.bin'
113 return image_file
114
115 def BuildUpdateImage(self, image_path):
116 stateful_file = '%s/stateful.image' % image_path
117 kernel_file = '%s/kernel.image' % image_path
118 rootfs_file = '%s/rootfs.image' % image_path
119
120 image_file = self.GetImageBinPath(image_path)
121 bin_path = os.path.join(image_path, image_file)
122
123 # Get appropriate update.gz to compare timestamps.
100 if self.serve_only: 124 if self.serve_only:
101 err = os.system('cd %s && unzip -o image.zip %s unpack_partitions.sh' % 125 cached_update_file = os.path.join(image_path, 'update.gz')
102 (image_path, image_file)) 126 else:
103 if err: 127 cached_update_file = os.path.join(self.static_dir, 'update.gz')
128
129 # Check whether we need to re-create if the original image is newer.
130 if (os.path.exists(cached_update_file) and
131 os.path.getmtime(cached_update_file) >= os.path.getmtime(bin_path)):
132 web.debug('Using cached update image at %s instead of %s' %
133 (cached_update_file, bin_path))
134 else:
135 # Unpack zip file if we are serving from a directory.
136 if self.serve_only and not self.UnpackZip(image_path, image_file):
104 web.debug('unzip image.zip failed.') 137 web.debug('unzip image.zip failed.')
105 return False 138 return False
106 139
107 os.system('rm -f %s/part_*' % image_path) 140 if not self.UnpackImage(image_path, image_file, stateful_file,
108 os.system('cd %s && ./unpack_partitions.sh %s' % (image_path, image_file)) 141 kernel_file, rootfs_file):
109 shutil.move(os.path.join(image_path, 'part_2'), kernel_file) 142 web.debug('Failed to unpack image.')
110 shutil.move(os.path.join(image_path, 'part_3'), rootfs_file) 143 return False
111 os.system('rm -f %s/part_*' % image_path)
112 return True
113 144
114 def BuildUpdateImage(self, image_path): 145 update_file = os.path.join(image_path, 'update.gz')
115 kernel_file = '%s/kernel.image' % image_path 146 web.debug('Generating update image %s' % update_file)
116 rootfs_file = '%s/rootfs.image' % image_path 147 mkupdate_command = '%s/mk_memento_images.sh %s %s' % \
148 (self.scripts_dir, kernel_file, rootfs_file)
149 if os.system(mkupdate_command) != 0:
150 web.debug('Failed to create update image')
151 return False
117 152
118 if not self.UnpackImage(image_path, kernel_file, rootfs_file): 153 mkstatefulupdate_command = 'gzip %s' % stateful_file
119 web.debug('failed to unpack image.') 154 if os.system(mkstatefulupdate_command) != 0:
120 return False 155 web.debug('Failed to create stateful update image')
156 return False
121 157
122 update_file = '%s/update.gz' % image_path 158 # Add gz suffix
123 if (os.path.exists(update_file) and 159 stateful_file = '%s.gz' % stateful_file
124 os.path.getmtime(update_file) >= os.path.getmtime(rootfs_file)): 160
125 web.debug('Found cached update image %s/update.gz' % image_path) 161 # Cleanup of image files
126 else: 162 os.remove(kernel_file)
127 web.debug('generating update image %s' % update_file) 163 os.remove(rootfs_file)
128 mkupdate = ('%s/mk_memento_images.sh %s %s' % 164 if not self.serve_only:
129 (self.scripts_dir, kernel_file, rootfs_file)) 165 try:
130 web.debug(mkupdate) 166 web.debug('Found a new image to serve, copying it to static')
131 err = os.system(mkupdate) 167 shutil.copy(update_file, self.static_dir)
132 if err != 0: 168 shutil.copy(stateful_file, self.static_dir)
133 web.debug('failed to create update image') 169 os.remove(update_file)
134 return False 170 os.remove(stateful_file)
135 if not self.serve_only: 171 except Exception, e:
136 web.debug('Found an image, copying it to static') 172 web.debug('%s' % e)
137 try: 173 return False
138 shutil.copy(update_file, self.static_dir)
139 except Exception, e:
140 web.debug('Unable to copy %s to %s' % (update_file, self.static_dir))
141 return False
142 return True 174 return True
143 175
144 def GetSize(self, update_path): 176 def GetSize(self, update_path):
145 return os.path.getsize(update_path) 177 return os.path.getsize(update_path)
146 178
147 def GetHash(self, update_path): 179 def GetHash(self, update_path):
148 cmd = "cat %s | openssl sha1 -binary | openssl base64 | tr \'\\n\' \' \';" \ 180 cmd = "cat %s | openssl sha1 -binary | openssl base64 | tr \'\\n\' \' \';" \
149 % update_path 181 % update_path
150 return os.popen(cmd).read().rstrip() 182 return os.popen(cmd).read().rstrip()
151 183
(...skipping 19 matching lines...) Expand all
171 'release_image': '6-release.gz', 203 'release_image': '6-release.gz',
172 'release_checksum': 'AtiI8B64agHVN+yeBAyiNMX3+HM=', 204 'release_checksum': 'AtiI8B64agHVN+yeBAyiNMX3+HM=',
173 'oempartitionimg_image': '6-oem.gz', 205 'oempartitionimg_image': '6-oem.gz',
174 'oempartitionimg_checksum': 'AtiI8B64agHVN+yeBAyiNMX3+HM=', 206 'oempartitionimg_checksum': 'AtiI8B64agHVN+yeBAyiNMX3+HM=',
175 'stateimg_image': '6-state.gz', 207 'stateimg_image': '6-state.gz',
176 'stateimg_checksum': 'AtiI8B64agHVN+yeBAyiNMX3+HM=' 208 'stateimg_checksum': 'AtiI8B64agHVN+yeBAyiNMX3+HM='
177 }, 209 },
178 ] 210 ]
179 The server will look for the files by name in the static files 211 The server will look for the files by name in the static files
180 directory. 212 directory.
181 213
182 If validate_checksums is True, validates checksums and exits. If 214 If validate_checksums is True, validates checksums and exits. If
183 a checksum mismatch is found, it's printed to the screen. 215 a checksum mismatch is found, it's printed to the screen.
184 """ 216 """
185 f = open(filename, 'r') 217 f = open(filename, 'r')
186 output = {} 218 output = {}
187 exec(f.read(), output) 219 exec(f.read(), output)
188 self.factory_config = output['config'] 220 self.factory_config = output['config']
189 success = True 221 success = True
190 for stanza in self.factory_config: 222 for stanza in self.factory_config:
191 for kind in ('factory', 'oempartitionimg', 'release', 'stateimg'): 223 for kind in ('factory', 'oempartitionimg', 'release', 'stateimg'):
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
260 # In case we configured images to be hosted elsewhere 292 # In case we configured images to be hosted elsewhere
261 # (e.g. buildbot's httpd), use that. Otherwise, serve it 293 # (e.g. buildbot's httpd), use that. Otherwise, serve it
262 # ourselves using web.py's static resource handler. 294 # ourselves using web.py's static resource handler.
263 if self.static_urlbase: 295 if self.static_urlbase:
264 urlbase = self.static_urlbase 296 urlbase = self.static_urlbase
265 else: 297 else:
266 urlbase = 'http://%s/static/archive/' % hostname 298 urlbase = 'http://%s/static/archive/' % hostname
267 299
268 url = '%s/%s/update.gz' % (urlbase, label) 300 url = '%s/%s/update.gz' % (urlbase, label)
269 return self.GetUpdatePayload(hash, size, url) 301 return self.GetUpdatePayload(hash, size, url)
270 web.debug( 'DONE') 302 web.debug('DONE')
271 else: 303 else:
272 web.debug('update found %s ' % latest_version) 304 web.debug('update found %s ' % latest_version)
273 ok = self.BuildUpdateImage(latest_image_path) 305 ok = self.BuildUpdateImage(latest_image_path)
274 if ok != True: 306 if ok != True:
275 web.debug('Failed to build an update image') 307 web.debug('Failed to build an update image')
276 return self.GetNoUpdatePayload() 308 return self.GetNoUpdatePayload()
277 309
278 hash = self.GetHash('%s/update.gz' % self.static_dir) 310 hash = self.GetHash('%s/update.gz' % self.static_dir)
279 size = self.GetSize('%s/update.gz' % self.static_dir) 311 size = self.GetSize('%s/update.gz' % self.static_dir)
280 312
281 url = 'http://%s/static/update.gz' % hostname 313 url = 'http://%s/static/update.gz' % hostname
282 return self.GetUpdatePayload(hash, size, url) 314 return self.GetUpdatePayload(hash, size, url)
OLDNEW
« no previous file with comments | « no previous file | src/platform/dev/stateful_update.sh » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698