Index: src/platform/dev/autoupdate.py |
diff --git a/src/platform/dev/autoupdate.py b/src/platform/dev/autoupdate.py |
index eb5b9ac847f19025ebe8e304deeda36a2a341540..4461533e45d98a53db59f354226c1e2ef19a2495 100644 |
--- a/src/platform/dev/autoupdate.py |
+++ b/src/platform/dev/autoupdate.py |
@@ -9,21 +9,27 @@ import os |
import web |
class Autoupdate(BuildObject): |
- |
# Basic functionality of handling ChromeOS autoupdate pings |
# and building/serving update images. |
# TODO(rtc): Clean this code up and write some tests. |
+ def __init__(self, serve_only=None, test_image=False, *args, **kwargs): |
+ self.serve_only = serve_only |
+ if serve_only: |
+ web.debug('Autoupdate in "serve update images only" mode.') |
+ self.test_image=test_image |
+ super(Autoupdate, self).__init__(*args, **kwargs) |
+ |
def GetUpdatePayload(self, hash, size, url): |
payload = """<?xml version="1.0" encoding="UTF-8"?> |
<gupdate xmlns="http://www.google.com/update2/response" protocol="2.0"> |
<app appid="{%s}" status="ok"> |
<ping status="ok"/> |
- <updatecheck |
- codebase="%s" |
- hash="%s" |
- needsadmin="false" |
- size="%s" |
+ <updatecheck |
+ codebase="%s" |
+ hash="%s" |
+ needsadmin="false" |
+ size="%s" |
status="ok"/> |
</app> |
</gupdate> |
@@ -42,14 +48,14 @@ class Autoupdate(BuildObject): |
return payload % self.app_id |
def GetLatestImagePath(self, board_id): |
- cmd = "%s/get_latest_image.sh --board %s" % (self.scripts_dir, board_id) |
+ cmd = '%s/get_latest_image.sh --board %s' % (self.scripts_dir, board_id) |
return os.popen(cmd).read().strip() |
def GetLatestVersion(self, latest_image_path): |
latest_version = latest_image_path.split('/')[-1] |
# Removes the portage build prefix. |
- latest_version = latest_version.lstrip("g-") |
+ latest_version = latest_version.lstrip('g-') |
return latest_version.split('-')[0] |
def CanUpdate(self, client_version, latest_version): |
@@ -58,7 +64,7 @@ class Autoupdate(BuildObject): |
""" |
client_tokens = client_version.split('.') |
latest_tokens = latest_version.split('.') |
- web.debug("client version %s latest version %s" \ |
+ web.debug('client version %s latest version %s' \ |
% (client_version, latest_version)) |
for i in range(0,4): |
if int(latest_tokens[i]) == int(client_tokens[i]): |
@@ -67,56 +73,88 @@ class Autoupdate(BuildObject): |
return False |
def BuildUpdateImage(self, image_path): |
- image_file = "%s/rootfs.image" % image_path |
- web.debug("checking image file %s/update.gz" % image_path) |
- if not os.path.exists("%s/update.gz" % image_path): |
- mkupdate = "%s/mk_memento_images.sh %s" % (self.scripts_dir, image_file) |
+ if self.test_image: |
+ image_file = '%s/rootfs_test.image' % image_path |
+ else: |
+ image_file = '%s/rootfs.image' % image_path |
+ update_file = '%s/update.gz' % image_path |
+ if (os.path.exists(update_file) and |
+ os.path.getmtime(update_file) >= os.path.getmtime(image_file)): |
+ web.debug('Found cached update image %s/update.gz' % image_path) |
+ else: |
+ web.debug('generating update image %s/update.gz' % image_path) |
+ mkupdate = '%s/mk_memento_images.sh %s' % (self.scripts_dir, image_file) |
web.debug(mkupdate) |
err = os.system(mkupdate) |
if err != 0: |
- web.debug("failed to create update image") |
+ web.debug('failed to create update image') |
+ return False |
+ if not self.serve_only: |
+ web.debug('Found an image, copying it to static') |
+ try: |
+ shutil.copyfile('%s/update.gz' % image_path, self.static_dir) |
+ except Exception, e: |
+ web.debug('Unable to copy update.gz from %s to %s' \ |
+ % (image_path, self.static_dir)) |
return False |
- |
- web.debug("Found an image, copying it to static") |
- err = os.system("cp %s/update.gz %s" % (image_path, self.static_dir)) |
- if err != 0: |
- web.debug("Unable to move update.gz from %s to %s" \ |
- % (image_path, self.static_dir)) |
- return False |
return True |
def GetSize(self, update_path): |
return os.path.getsize(update_path) |
def GetHash(self, update_path): |
- cmd = "cat %s | openssl sha1 -binary | openssl base64 | tr \'\\n\' \' \';" \ |
- % update_path |
- web.debug(cmd) |
- return os.popen(cmd).read() |
- |
- def HandleUpdatePing(self, data): |
+ update_dir = os.path.dirname(update_path) |
+ if not os.path.exists('%s/cksum' % update_dir): |
+ cmd = ('cat %s | openssl sha1 -binary' |
+ '| openssl base64 | tr \'\\n\' \' \' | tee %s/cksum' % |
+ (update_path, update_dir)) |
+ web.debug(cmd) |
+ return os.popen(cmd).read() |
+ else: |
+ web.debug('using cached checksum for %s' % update_path) |
+ return file('%s/cksum' % update_dir).read() |
+ |
+ def HandleUpdatePing(self, data, label=None): |
update_dom = minidom.parseString(data) |
root = update_dom.firstChild |
- query = root.getElementsByTagName("o:app")[0] |
+ query = root.getElementsByTagName('o:app')[0] |
client_version = query.getAttribute('version') |
board_id = query.hasAttribute('board') and query.getAttribute('board') \ |
- or "x86-generic" |
+ or 'x86-generic' |
latest_image_path = self.GetLatestImagePath(board_id) |
latest_version = self.GetLatestVersion(latest_image_path) |
- if client_version != "ForcedUpdate" \ |
+ if client_version != 'ForcedUpdate' \ |
and not self.CanUpdate(client_version, latest_version): |
- web.debug("no update") |
+ web.debug('no update') |
return self.GetNoUpdatePayload() |
- |
- web.debug("update found %s " % latest_version) |
- ok = self.BuildUpdateImage(latest_image_path) |
- if ok != True: |
- web.debug("Failed to build an update image") |
- return self.GetNoUpdatePayload() |
- |
- hash = self.GetHash("%s/update.gz" % self.static_dir) |
- size = self.GetSize("%s/update.gz" % self.static_dir) |
hostname = web.ctx.host |
- url = "http://%s/static/update.gz" % hostname |
- return self.GetUpdatePayload(hash, size, url) |
- |
+ if label: |
+ web.debug('Client requested version %s' % label) |
+ # Check that matching build exists |
+ image_path = '%s/%s' % (self.static_dir, label) |
+ if not os.path.exists(image_path): |
+ web.debug('%s not found.' % image_path) |
+ return self.GetNoUpdatePayload() |
+ # Construct a response |
+ ok = self.BuildUpdateImage(image_path) |
+ if ok != True: |
+ web.debug('Failed to build an update image') |
+ return self.GetNoUpdatePayload() |
+ web.debug('serving update: ') |
+ hash = self.GetHash('%s/%s/update.gz' % (self.static_dir, label)) |
+ size = self.GetSize('%s/%s/update.gz' % (self.static_dir, label)) |
+ url = 'http://%s/static/archive/%s/update.gz' % (hostname, label) |
+ return self.GetUpdatePayload(hash, size, url) |
+ web.debug( 'DONE') |
+ else: |
+ web.debug('update found %s ' % latest_version) |
+ ok = self.BuildUpdateImage(latest_image_path) |
+ if ok != True: |
+ web.debug('Failed to build an update image') |
+ return self.GetNoUpdatePayload() |
+ |
+ hash = self.GetHash('%s/update.gz' % self.static_dir) |
+ size = self.GetSize('%s/update.gz' % self.static_dir) |
+ |
+ url = 'http://%s/static/update.gz' % hostname |
+ return self.GetUpdatePayload(hash, size, url) |