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

Side by Side Diff: autoupdate.py

Issue 5297002: --archive_dir will now serve existing update.gz (Closed) Base URL: http://git.chromium.org/git/dev-util.git@master
Patch Set: Code review fixes. Created 10 years 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | autoupdate_unittest.py » ('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-2010 The Chromium OS Authors. All rights reserved. 1 # Copyright (c) 2009-2010 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 cherrypy 8 import cherrypy
9 import os 9 import os
10 import shutil 10 import shutil
11 import subprocess 11 import subprocess
12 import time 12 import time
13 13
14 14
15 def _LogMessage(message): 15 def _LogMessage(message):
16 cherrypy.log(message, 'UPDATE') 16 cherrypy.log(message, 'UPDATE')
17 17
18 UPDATE_FILE='update.gz' 18 UPDATE_FILE='update.gz'
19 STATEFUL_FILE='stateful.tgz' 19 STATEFUL_FILE='stateful.tgz'
20 20
21 class Autoupdate(BuildObject): 21 class Autoupdate(BuildObject):
22 """Class that contains functionality that handles Chrome OS update pings. 22 """Class that contains functionality that handles Chrome OS update pings.
23 23
24 Members: 24 Members:
25 serve_only: Serve images from a pre-built image.zip file. static_dir 25 serve_only: Serve only pre-built updates. static_dir must contain update.gz
26 must be set to the location of the image.zip. 26 and stateful.tgz.
27 factory_config: Path to the factory config file if handling factory 27 factory_config: Path to the factory config file if handling factory
28 requests. 28 requests.
29 use_test_image: Use chromiumos_test_image.bin rather than the standard. 29 use_test_image: Use chromiumos_test_image.bin rather than the standard.
30 static_url_base: base URL, other than devserver, for update images. 30 static_url_base: base URL, other than devserver, for update images.
31 client_prefix: The prefix for the update engine client. 31 client_prefix: The prefix for the update engine client.
32 forced_image: Path to an image to use for all updates. 32 forced_image: Path to an image to use for all updates.
33 """ 33 """
34 34
35 def __init__(self, serve_only=None, test_image=False, urlbase=None, 35 def __init__(self, serve_only=None, test_image=False, urlbase=None,
36 factory_config_path=None, client_prefix=None, 36 factory_config_path=None, client_prefix=None,
37 forced_image=None, forced_payload=None, 37 forced_image=None, forced_payload=None,
38 port=8080, src_image='', vm=False, board=None, 38 port=8080, src_image='', vm=False, board=None,
39 *args, **kwargs): 39 *args, **kwargs):
40 super(Autoupdate, self).__init__(*args, **kwargs) 40 super(Autoupdate, self).__init__(*args, **kwargs)
41 self.serve_only = serve_only 41 self.serve_only = serve_only
42 self.factory_config = factory_config_path 42 self.factory_config = factory_config_path
43 self.use_test_image = test_image 43 self.use_test_image = test_image
44 if urlbase: 44 if urlbase:
45 self.urlbase = urlbase 45 self.urlbase = urlbase
46 else: 46 else:
47 self.urlbase = None 47 self.urlbase = None
48 48
49 self.client_prefix = client_prefix 49 self.client_prefix = client_prefix
50 self.forced_image = forced_image 50 self.forced_image = forced_image
51 self.forced_payload = forced_payload 51 self.forced_payload = forced_payload
52 self.src_image = src_image 52 self.src_image = src_image
53 self.vm = vm 53 self.vm = vm
54 self.board = board 54 self.board = board
55 55
56 # Caching is enabled if we are not doing serve_only
57 # aka if --archive_dir was not passed in.
58 self.caching_enabled = not self.serve_only
59
60 # Track update pregeneration, so we don't recopy if not needed. 56 # Track update pregeneration, so we don't recopy if not needed.
61 self.pregenerated = False 57 self.pregenerated = False
62 58
63 def _GetSecondsSinceMidnight(self): 59 def _GetSecondsSinceMidnight(self):
64 """Returns the seconds since midnight as a decimal value.""" 60 """Returns the seconds since midnight as a decimal value."""
65 now = time.localtime() 61 now = time.localtime()
66 return now[3] * 3600 + now[4] * 60 + now[5] 62 return now[3] * 3600 + now[4] * 60 + now[5]
67 63
68 def _GetDefaultBoardID(self): 64 def _GetDefaultBoardID(self):
69 """Returns the default board id stored in .default_board.""" 65 """Returns the default board id stored in .default_board."""
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
317 update filename (not directory) relative to static_image_dir on success, 313 update filename (not directory) relative to static_image_dir on success,
318 or None 314 or None
319 """ 315 """
320 _LogMessage('Generating update for src %s image %s' % (self.src_image, 316 _LogMessage('Generating update for src %s image %s' % (self.src_image,
321 image_path)) 317 image_path))
322 318
323 # If it was pregenerated, don't regenerate 319 # If it was pregenerated, don't regenerate
324 if self.pregenerated: 320 if self.pregenerated:
325 return UPDATE_FILE 321 return UPDATE_FILE
326 322
327 if not self.caching_enabled:
328 return self.GenerateUpdateImage(image_path, static_image_dir)
329
330 # Which sub_dir of static_image_dir should hold our cached update image 323 # Which sub_dir of static_image_dir should hold our cached update image
331 cache_sub_dir = self.FindCachedUpdateImageSubDir(self.src_image, image_path) 324 cache_sub_dir = self.FindCachedUpdateImageSubDir(self.src_image, image_path)
332 _LogMessage('Caching in sub_dir "%s"' % cache_sub_dir) 325 _LogMessage('Caching in sub_dir "%s"' % cache_sub_dir)
333 326
334 # The cached payloads exist in a cache dir 327 # The cached payloads exist in a cache dir
335 cache_update_payload = os.path.join(static_image_dir, 328 cache_update_payload = os.path.join(static_image_dir,
336 cache_sub_dir, 329 cache_sub_dir,
337 UPDATE_FILE) 330 UPDATE_FILE)
338 cache_stateful_payload = os.path.join(static_image_dir, 331 cache_stateful_payload = os.path.join(static_image_dir,
339 cache_sub_dir, 332 cache_sub_dir,
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
391 384
392 # Check to see whether or not we should update. 385 # Check to see whether or not we should update.
393 if client_version != 'ForcedUpdate' and not self._CanUpdate( 386 if client_version != 'ForcedUpdate' and not self._CanUpdate(
394 client_version, latest_version): 387 client_version, latest_version):
395 _LogMessage('no update') 388 _LogMessage('no update')
396 return None 389 return None
397 390
398 return self.GenerateUpdateImageWithCache(latest_image_path, 391 return self.GenerateUpdateImageWithCache(latest_image_path,
399 static_image_dir=static_image_dir) 392 static_image_dir=static_image_dir)
400 393
401 def GenerateImageFromZip(self, static_image_dir):
402 """Generates an update from an image zip file.
403
404 This method assumes you have an image.zip in directory you are serving
405 from. If this file is newer than a previously cached file, it will unzip
406 this file, create a payload and serve it.
407
408 Args:
409 static_image_dir: Directory where the zip file exists.
410 Returns:
411 Name of the update payload relative to static_image_dir if successful.
412 """
413 _LogMessage('Preparing to generate update from zip in %s.' %
414 static_image_dir)
415 image_path = os.path.join(static_image_dir, self._GetImageName())
416 zip_file_path = os.path.join(static_image_dir, 'image.zip')
417
418 # TODO(dgarrett): Either work caching into this path before
419 # we unpack, or remove zip support (sosa is considering).
420 # It does currently cache, but after the unpack.
421
422 if not self._UnpackZip(static_image_dir):
423 _LogMessage('unzip image.zip failed.')
424 return None
425
426 return self.GenerateUpdateImageWithCache(image_path,
427 static_image_dir=static_image_dir)
428
429 def ImportFactoryConfigFile(self, filename, validate_checksums=False): 394 def ImportFactoryConfigFile(self, filename, validate_checksums=False):
430 """Imports a factory-floor server configuration file. The file should 395 """Imports a factory-floor server configuration file. The file should
431 be in this format: 396 be in this format:
432 config = [ 397 config = [
433 { 398 {
434 'qual_ids': set([1, 2, 3, "x86-generic"]), 399 'qual_ids': set([1, 2, 3, "x86-generic"]),
435 'factory_image': 'generic-factory.gz', 400 'factory_image': 'generic-factory.gz',
436 'factory_checksum': 'AtiI8B64agHVN+yeBAyiNMX3+HM=', 401 'factory_checksum': 'AtiI8B64agHVN+yeBAyiNMX3+HM=',
437 'release_image': 'generic-release.gz', 402 'release_image': 'generic-release.gz',
438 'release_checksum': 'AtiI8B64agHVN+yeBAyiNMX3+HM=', 403 'release_checksum': 'AtiI8B64agHVN+yeBAyiNMX3+HM=',
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
519 # setting sha-256 to an empty string. 484 # setting sha-256 to an empty string.
520 return self.GetUpdatePayload(checksum, '', size, url, is_delta_format) 485 return self.GetUpdatePayload(checksum, '', size, url, is_delta_format)
521 486
522 def GenerateUpdatePayloadForNonFactory(self, board_id, client_version, 487 def GenerateUpdatePayloadForNonFactory(self, board_id, client_version,
523 static_image_dir): 488 static_image_dir):
524 """Generates an update for non-factory image. 489 """Generates an update for non-factory image.
525 490
526 Returns: 491 Returns:
527 file name relative to static_image_dir on success. 492 file name relative to static_image_dir on success.
528 """ 493 """
494 dest_path = os.path.join(static_image_dir, UPDATE_FILE)
495 dest_stateful = os.path.join(static_image_dir, STATEFUL_FILE)
496
529 if self.forced_payload: 497 if self.forced_payload:
530 # If the forced payload is not already in our static_image_dir, 498 # If the forced payload is not already in our static_image_dir,
531 # copy it there. 499 # copy it there.
532 src_path = os.path.abspath(self.forced_payload) 500 src_path = os.path.abspath(self.forced_payload)
533 dest_path = os.path.join(static_image_dir, UPDATE_FILE)
534 501
535 src_stateful = os.path.join(os.path.dirname(src_path), 502 src_stateful = os.path.join(os.path.dirname(src_path),
536 STATEFUL_FILE) 503 STATEFUL_FILE)
537 dest_stateful = os.path.join(static_image_dir,
538 STATEFUL_FILE)
539 504
540 # Only copy the files if the source directory is different from dest. 505 # Only copy the files if the source directory is different from dest.
541 if os.path.dirname(src_path) != os.path.abspath(static_image_dir): 506 if os.path.dirname(src_path) != os.path.abspath(static_image_dir):
542 self._Copy(src_path, dest_path) 507 self._Copy(src_path, dest_path)
543 508
544 # The stateful payload is optional. 509 # The stateful payload is optional.
545 if os.path.exists(src_stateful): 510 if os.path.exists(src_stateful):
546 self._Copy(src_stateful, dest_stateful) 511 self._Copy(src_stateful, dest_stateful)
547 else: 512 else:
548 _LogMessage('WARN: %s not found. Expected for dev and test builds.' % 513 _LogMessage('WARN: %s not found. Expected for dev and test builds.' %
549 STATEFUL_FILE) 514 STATEFUL_FILE)
550 if os.path.exists(dest_stateful): 515 if os.path.exists(dest_stateful):
551 os.remove(dest_stateful) 516 os.remove(dest_stateful)
552 517
553 return UPDATE_FILE 518 return UPDATE_FILE
554 elif self.forced_image: 519 elif self.forced_image:
555 return self.GenerateUpdateImageWithCache( 520 return self.GenerateUpdateImageWithCache(
556 self.forced_image, 521 self.forced_image,
557 static_image_dir=static_image_dir) 522 static_image_dir=static_image_dir)
558 elif self.serve_only: 523 elif self.serve_only:
559 return self.GenerateImageFromZip(static_image_dir) 524 # Warn if update or stateful files can't be found.
525 if not os.path.exists(dest_path):
526 _LogMessage('WARN: %s not found. Expected for dev and test builds.' %
527 UPDATE_FILE)
528
529 if not os.path.exists(dest_stateful):
530 _LogMessage('WARN: %s not found. Expected for dev and test builds.' %
531 STATEFUL_FILE)
532
533 return UPDATE_FILE
560 else: 534 else:
561 if board_id: 535 if board_id:
562 return self.GenerateLatestUpdateImage(board_id, 536 return self.GenerateLatestUpdateImage(board_id,
563 client_version, 537 client_version,
564 static_image_dir) 538 static_image_dir)
565 539
566 _LogMessage('You must set --board for pre-generating latest update.') 540 _LogMessage('You must set --board for pre-generating latest update.')
567 return None 541 return None
568 542
569 def PreGenerateUpdate(self): 543 def PreGenerateUpdate(self):
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
648 is_delta_format = self._IsDeltaFormatFile(filename) 622 is_delta_format = self._IsDeltaFormatFile(filename)
649 if label: 623 if label:
650 url = '%s/%s/%s' % (static_urlbase, label, payload_path) 624 url = '%s/%s/%s' % (static_urlbase, label, payload_path)
651 else: 625 else:
652 url = '%s/%s' % (static_urlbase, payload_path) 626 url = '%s/%s' % (static_urlbase, payload_path)
653 627
654 _LogMessage('Responding to client to use url %s to get image.' % url) 628 _LogMessage('Responding to client to use url %s to get image.' % url)
655 return self.GetUpdatePayload(hash, sha256, size, url, is_delta_format) 629 return self.GetUpdatePayload(hash, sha256, size, url, is_delta_format)
656 else: 630 else:
657 return self.GetNoUpdatePayload() 631 return self.GetNoUpdatePayload()
OLDNEW
« no previous file with comments | « no previous file | autoupdate_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698