mirror of
https://github.com/flatcar/scripts.git
synced 2025-09-23 22:51:03 +02:00
Upgrade cros_image_to_target.py to support Omaha v3 protocol.
As part of the efforts to support HTTP-based downloads for autoupdate, we are upgrading update_engine from Omaha v2 to v3. So, we need to update cros_image_to_target.py to also understand the v3 XML. BUG=chromium-os:35930 TEST=Successfully updated my ZGB which was running the v3 update_engine. Change-Id: I2b4831c1e87ccf064e79cd6d34205f19aedc9d57 Reviewed-on: https://gerrit.chromium.org/gerrit/37065 Reviewed-by: Chris Sosa <sosa@chromium.org> Reviewed-by: Paul Stewart <pstew@chromium.org> Commit-Ready: Chris Sosa <sosa@chromium.org> Tested-by: Chris Sosa <sosa@chromium.org>
This commit is contained in:
parent
bd9212c1ce
commit
b797d74253
@ -39,6 +39,42 @@ STATEFUL_FILENAME = 'stateful.tgz'
|
||||
# How long do we wait for the server to start before launching client
|
||||
SERVER_STARTUP_WAIT = 1
|
||||
|
||||
UPDATE_RESPONSE = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<response protocol="3.0">
|
||||
<daystart elapsed_seconds="%(time_elapsed)s"/>
|
||||
<app appid="{%(appid)s}" status="ok">
|
||||
<ping status="ok"/>
|
||||
<updatecheck status="ok">
|
||||
<urls>
|
||||
<url codebase="%(codebase)s/"/>
|
||||
</urls>
|
||||
<manifest version="9999.0.0">
|
||||
<packages>
|
||||
<package hash="%(sha1)s" name="%(filename)s" size="%(size)s"
|
||||
required="true"/>
|
||||
</packages>
|
||||
<actions>
|
||||
<action event="postinstall"
|
||||
ChromeOSVersion="9999.0.0"
|
||||
sha256="%(sha256)s"
|
||||
needsadmin="false"
|
||||
IsDelta="%(is_delta_format)s"
|
||||
%(extra_attr)s />
|
||||
</actions>
|
||||
</manifest>
|
||||
</updatecheck>
|
||||
</app>
|
||||
</response>
|
||||
"""
|
||||
NO_UPDATE_RESPONSE = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<response" protocol="3.0">
|
||||
<daystart elapsed_seconds="%(time_elapsed)s"/>
|
||||
<app appid="{%(appid)s}" status="ok">
|
||||
<ping status="ok"/>
|
||||
<updatecheck status="noupdate"/>
|
||||
</app>
|
||||
</response>
|
||||
"""
|
||||
|
||||
class Command(object):
|
||||
"""Shell command ease-ups for Python."""
|
||||
@ -449,34 +485,6 @@ class StringUpdateResponse(UpdateResponse):
|
||||
class PingUpdateResponse(StringUpdateResponse):
|
||||
"""Respond to a client ping with pre-fab XML response."""
|
||||
|
||||
app_id = '87efface-864d-49a5-9bb3-4b050a7c227a'
|
||||
xmlns = 'http://www.google.com/update2/response'
|
||||
payload_success_template = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gupdate xmlns="%s" protocol="2.0">
|
||||
<daystart elapsed_seconds="%s"/>
|
||||
<app appid="{%s}" status="ok">
|
||||
<ping status="ok"/>
|
||||
<updatecheck
|
||||
codebase="%s"
|
||||
hash="%s"
|
||||
sha256="%s"
|
||||
IsDelta="true"
|
||||
needsadmin="false"
|
||||
size="%s"
|
||||
status="ok"/>
|
||||
</app>
|
||||
</gupdate>
|
||||
"""
|
||||
payload_failure_template = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gupdate xmlns="%s" protocol="2.0">
|
||||
<daystart elapsed_seconds="%s"/>
|
||||
<app appid="{%s}" status="ok">
|
||||
<ping status="ok"/>
|
||||
<updatecheck status="noupdate"/>
|
||||
</app>
|
||||
</gupdate>
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.content_type = 'text/xml'
|
||||
|
||||
@ -486,25 +494,90 @@ class PingUpdateResponse(StringUpdateResponse):
|
||||
PingUpdateResponse.file_sha256 = filesha256
|
||||
PingUpdateResponse.file_size = filesize
|
||||
|
||||
def GetCommonResponseValues(self):
|
||||
"""Returns a dictionary of default values that'll be substituted in the
|
||||
response irrespective of the protocol version."""
|
||||
response_values = {}
|
||||
response_values['appid'] = '87efface-864d-49a5-9bb3-4b050a7c227a'
|
||||
response_values['time_elapsed'] = self.SecondsSinceMidnight()
|
||||
return response_values
|
||||
|
||||
def GetSubstitutedResponse(self, response_template, response_values):
|
||||
"""Substitutes the response template with response_values.
|
||||
|
||||
Args:
|
||||
response_dict: Canned response template
|
||||
response_values: Values to be substituted in the canned template.
|
||||
Returns:
|
||||
Xml string to be passed back to client.
|
||||
Raises:
|
||||
AutoupdateError if required response values are not present.
|
||||
"""
|
||||
try:
|
||||
response_xml = response_template % response_values
|
||||
return response_xml
|
||||
except KeyError as e:
|
||||
self.Fatal('Missing response value: %s' % e)
|
||||
|
||||
def GetUpdateResponse(self, sha1, sha256, size, url, is_delta_format):
|
||||
"""Returns a response to the client corresponding to a new update.
|
||||
|
||||
Args:
|
||||
sha1: SHA1 hash of update blob
|
||||
sha256: SHA256 hash of update blob
|
||||
size: size of update blob
|
||||
url: where to find update blob
|
||||
is_delta_format: true if url refers to a delta payload
|
||||
Returns:
|
||||
Xml string to be passed back to client.
|
||||
"""
|
||||
response_values = self.GetCommonResponseValues()
|
||||
response_values['sha1'] = sha1
|
||||
response_values['sha256'] = sha256
|
||||
response_values['size'] = size
|
||||
response_values['url'] = url
|
||||
(codebase, filename) = os.path.split(url)
|
||||
response_values['codebase'] = codebase
|
||||
response_values['filename'] = filename
|
||||
response_values['is_delta_format'] = is_delta_format
|
||||
response_values['extra_attr'] = ''
|
||||
response_xml = self.GetSubstitutedResponse(UPDATE_RESPONSE,
|
||||
response_values)
|
||||
return response_xml
|
||||
|
||||
def GetNoUpdateResponse(self):
|
||||
"""Returns a response to the client corresponding to no update."""
|
||||
response_values = self.GetCommonResponseValues()
|
||||
response_xml = self.GetSubstitutedResponse(NO_UPDATE_RESPONSE,
|
||||
response_values)
|
||||
return response_xml
|
||||
|
||||
|
||||
def Reply(self, handler, send_content=True, post_data=None):
|
||||
"""Return (using StringResponse) an XML reply to ForcedUpdate clients."""
|
||||
|
||||
if not post_data:
|
||||
return UpdateResponse.Reply(self, handler)
|
||||
|
||||
request_version = (minidom.parseString(post_data).firstChild.
|
||||
getElementsByTagName('o:app')[0].
|
||||
getAttribute('version'))
|
||||
root = minidom.parseString(post_data)
|
||||
protocol = root.firstChild.getAttribute('protocol')
|
||||
if (protocol != '3.0'):
|
||||
raise BaseException('You first need to update your device to a build '
|
||||
'that uses Omaha v3 protocol for the update_engine.')
|
||||
|
||||
app = root.firstChild.getElementsByTagName('app')[0]
|
||||
request_version = app.getAttribute('version')
|
||||
|
||||
if request_version == 'ForcedUpdate':
|
||||
host, pdict = cgi.parse_header(handler.headers.getheader('Host'))
|
||||
self.string = (self.payload_success_template %
|
||||
(self.xmlns, self.SecondsSinceMidnight(),
|
||||
self.app_id, 'http://%s/%s' % (host, UPDATE_FILENAME),
|
||||
self.file_hash, self.file_sha256, self.file_size))
|
||||
url = 'http://%s/%s' % (host, UPDATE_FILENAME)
|
||||
self.string = self.GetUpdateResponse(self.file_hash,
|
||||
self.file_sha256,
|
||||
self.file_size,
|
||||
url,
|
||||
False) # is_delta_format
|
||||
else:
|
||||
self.string = (self.payload_failure_template %
|
||||
(self.xmlns, self.SecondsSinceMidnight(), self.app_id))
|
||||
self.string = (self.GetNoUpdateResponse())
|
||||
|
||||
StringUpdateResponse.Reply(self, handler, send_content)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user