blob: cdfd74b691ea1c29120e4b8b216b4c83c9b35126 [file] [log] [blame]
# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import BaseHTTPServer
import thread
import urlparse
from autotest_lib.client.bin import test, utils
from autotest_lib.client.common_lib import error, utils
def _split_url(url):
"""Splits a URL into the URL base and path."""
split_url = urlparse.urlsplit(url)
url_base = urlparse.urlunsplit(
(split_url.scheme, split_url.netloc, '', '', ''))
url_path = split_url.path
return url_base, url_path.lstrip('/')
class NanoOmahaDevserver(object):
"""Simple implementation of Omaha."""
class Handler(BaseHTTPServer.BaseHTTPRequestHandler):
"""Inner class for handling HTTP requests."""
_OMAHA_RESPONSE_TEMPLATE_HEAD = """
<response protocol=\"3.0\">
<daystart elapsed_seconds=\"44801\"/>
<app appid=\"{87efface-864d-49a5-9bb3-4b050a7c227a}\" status=\"ok\">
<ping status=\"ok\"/>
<updatecheck status=\"ok\">
<urls>
<url codebase=\"%s\"/>
</urls>
<manifest version=\"9999.0.0\">
<packages>
<package name=\"%s\" size=\"%d\" required=\"true\"/>
</packages>
<actions>
<action event=\"postinstall\"
ChromeOSVersion=\"9999.0.0\"
sha256=\"%s\"
needsadmin=\"false\"
IsDeltaPayload=\"false\"
"""
_OMAHA_RESPONSE_TEMPLATE_TAIL = """ />
</actions>
</manifest>
</updatecheck>
</app>
</response>
"""
def do_POST(self):
"""Handler for POST requests."""
if self.path == '/update':
(base, name) = _split_url(self.server._devserver._image_url)
response = self._OMAHA_RESPONSE_TEMPLATE_HEAD % (
base + '/', name,
self.server._devserver._image_size,
self.server._devserver._sha256)
if self.server._devserver._metadata_size:
response += ' MetadataSize="%d"\n' % (
self.server._devserver._metadata_size)
if self.server._devserver._metadata_signature:
response += ' MetadataSignatureRsa="%s"\n' % (
self.server._devserver._metadata_signature)
if self.server._devserver._public_key:
response += ' PublicKeyRsa="%s"\n' % (
self.server._devserver._public_key)
response += self._OMAHA_RESPONSE_TEMPLATE_TAIL
self.send_response(200)
self.send_header('Content-Type', 'application/xml')
self.end_headers()
self.wfile.write(response)
else:
self.send_response(500)
def start(self):
"""Starts the server."""
self._httpd = BaseHTTPServer.HTTPServer(('127.0.0.1', 0), self.Handler)
self._httpd._devserver = self
# Serve HTTP requests in a dedicated thread.
thread.start_new_thread(self._httpd.serve_forever, ())
self._port = self._httpd.socket.getsockname()[1]
def stop(self):
"""Stops the server."""
self._httpd.shutdown()
def get_port(self):
"""Returns the TCP port number the server is listening on."""
return self._port
def set_image_params(self, image_url, image_size, sha256,
metadata_size=None,
metadata_signature=None,
public_key=None):
"""Sets the values to return in the Omaha response. Only the
|image_url|, |image_size| and |sha256| parameters are
mandatory."""
self._image_url = image_url
self._image_size = image_size
self._sha256 = sha256
self._metadata_size = metadata_size
self._metadata_signature = metadata_signature
self._public_key = public_key
class autoupdate_CannedOmahaUpdate(test.test):
"""Client-side mechanism to update a DUT with a given image."""
version = 1
"""Restarts update_engine and attempts an update from the image
pointed to by |image_url| of size |image_size| with checksum
|image_sha256|. The |metadata_size|, |metadata_signature| and
|public_key| parameters are optional.
If the |allow_failure| parameter is True, then the test will
succeed even if the update failed."""
def run_once(self, image_url, image_size, image_sha256,
allow_failure=False,
metadata_size=None,
metadata_signature=None,
public_key=None):
utils.run('restart update-engine')
omaha = NanoOmahaDevserver()
omaha.set_image_params(image_url,
image_size,
image_sha256,
metadata_size,
metadata_signature,
public_key)
omaha.start()
try:
utils.run('update_engine_client -omaha_url ' +
'http://127.0.0.1:%d/update ' % omaha.get_port() +
'-update')
except error.CmdError:
omaha.stop()
if not allow_failure:
raise error.TestFail('Update attempt failed.')