| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 # | 2 # |
| 3 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 3 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
| 4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
| 5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
| 6 | 6 |
| 7 """Create and copy update image to target host. | 7 """Create and copy update image to target host. |
| 8 | 8 |
| 9 auto-update and devserver change out from beneath us often enough | 9 auto-update and devserver change out from beneath us often enough |
| 10 that despite having to duplicate a litte code, it seems that the | 10 that despite having to duplicate a litte code, it seems that the |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 import sys | 23 import sys |
| 24 import tempfile | 24 import tempfile |
| 25 import time | 25 import time |
| 26 import traceback | 26 import traceback |
| 27 | 27 |
| 28 from xml.dom import minidom | 28 from xml.dom import minidom |
| 29 | 29 |
| 30 | 30 |
| 31 # This is the default filename within the image directory to load updates from | 31 # This is the default filename within the image directory to load updates from |
| 32 DEFAULT_IMAGE_NAME = 'chromiumos_image.bin' | 32 DEFAULT_IMAGE_NAME = 'chromiumos_image.bin' |
| 33 DEFAULT_IMAGE_NAME_TEST = 'chromiumos_test_image.bin' |
| 33 | 34 |
| 34 # The filenames we provide to clients to pull updates | 35 # The filenames we provide to clients to pull updates |
| 35 UPDATE_FILENAME = 'update.gz' | 36 UPDATE_FILENAME = 'update.gz' |
| 36 STATEFUL_FILENAME = 'stateful.tgz' | 37 STATEFUL_FILENAME = 'stateful.tgz' |
| 37 | 38 |
| 38 # How long do we wait for the server to start before launching client | 39 # How long do we wait for the server to start before launching client |
| 39 SERVER_STARTUP_WAIT = 1 | 40 SERVER_STARTUP_WAIT = 1 |
| 40 | 41 |
| 41 | 42 |
| 42 class Command(object): | 43 class Command(object): |
| 43 """Shell command ease-ups for Python.""" | 44 """Shell command ease-ups for Python.""" |
| 44 | 45 |
| 45 def __init__(self, env): | 46 def __init__(self, env): |
| 46 self.env = env | 47 self.env = env |
| 47 | 48 |
| 48 def RunPipe(self, pipeline, infile=None, outfile=None, | 49 def RunPipe(self, pipeline, infile=None, outfile=None, |
| 49 capture=False, oneline=False): | 50 capture=False, oneline=False, hide_stderr=False): |
| 50 """Perform a command pipeline, with optional input/output filenames.""" | 51 """ |
| 52 Perform a command pipeline, with optional input/output filenames. |
| 53 |
| 54 hide_stderr Don't allow output of stderr (default False) |
| 55 """ |
| 51 | 56 |
| 52 last_pipe = None | 57 last_pipe = None |
| 53 while pipeline: | 58 while pipeline: |
| 54 cmd = pipeline.pop(0) | 59 cmd = pipeline.pop(0) |
| 55 kwargs = {} | 60 kwargs = {} |
| 56 if last_pipe is not None: | 61 if last_pipe is not None: |
| 57 kwargs['stdin'] = last_pipe.stdout | 62 kwargs['stdin'] = last_pipe.stdout |
| 58 elif infile: | 63 elif infile: |
| 59 kwargs['stdin'] = open(infile, 'rb') | 64 kwargs['stdin'] = open(infile, 'rb') |
| 60 if pipeline or capture: | 65 if pipeline or capture: |
| 61 kwargs['stdout'] = subprocess.PIPE | 66 kwargs['stdout'] = subprocess.PIPE |
| 62 elif outfile: | 67 elif outfile: |
| 63 kwargs['stdout'] = open(outfile, 'wb') | 68 kwargs['stdout'] = open(outfile, 'wb') |
| 69 if hide_stderr: |
| 70 kwargs['stderr'] = open('/dev/null', 'wb') |
| 64 | 71 |
| 65 self.env.Info('Running: %s' % ' '.join(cmd)) | 72 self.env.Debug('Running: %s' % ' '.join(cmd)) |
| 66 last_pipe = subprocess.Popen(cmd, **kwargs) | 73 last_pipe = subprocess.Popen(cmd, **kwargs) |
| 67 | 74 |
| 68 if capture: | 75 if capture: |
| 69 ret = last_pipe.communicate()[0] | 76 ret = last_pipe.communicate()[0] |
| 70 if not ret: | 77 if not ret: |
| 71 return None | 78 return None |
| 72 elif oneline: | 79 elif oneline: |
| 73 return ret.rstrip('\r\n') | 80 return ret.rstrip('\r\n') |
| 74 else: | 81 else: |
| 75 return ret | 82 return ret |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 132 [src, 'root@%s:%s' % | 139 [src, 'root@%s:%s' % |
| 133 (self.remote, dest)]]) | 140 (self.remote, dest)]]) |
| 134 | 141 |
| 135 | 142 |
| 136 class CrosEnv(object): | 143 class CrosEnv(object): |
| 137 """Encapsulates the ChromeOS build system environment functionality.""" | 144 """Encapsulates the ChromeOS build system environment functionality.""" |
| 138 | 145 |
| 139 REBOOT_START_WAIT = 5 | 146 REBOOT_START_WAIT = 5 |
| 140 REBOOT_WAIT_TIME = 60 | 147 REBOOT_WAIT_TIME = 60 |
| 141 | 148 |
| 142 def __init__(self, verbose=False): | 149 SILENT = 0 |
| 150 INFO = 1 |
| 151 DEBUG = 2 |
| 152 |
| 153 def __init__(self, verbose=SILENT): |
| 143 self.cros_root = os.path.dirname(os.path.abspath(sys.argv[0])) | 154 self.cros_root = os.path.dirname(os.path.abspath(sys.argv[0])) |
| 144 parent = os.path.dirname(self.cros_root) | 155 parent = os.path.dirname(self.cros_root) |
| 145 if os.path.exists(os.path.join(parent, 'chromeos-common.sh')): | 156 if os.path.exists(os.path.join(parent, 'chromeos-common.sh')): |
| 146 self.cros_root = parent | 157 self.cros_root = parent |
| 147 self.cmd = Command(self) | 158 self.cmd = Command(self) |
| 148 self.verbose = verbose | 159 self.verbose = verbose |
| 149 | 160 |
| 161 # do we have the pv progress tool? (sudo apt-get install pv) |
| 162 self.have_pv = True |
| 163 try: |
| 164 self.cmd.Output('pv', '--help') |
| 165 except OSError: |
| 166 self.have_pv = False |
| 167 |
| 150 def Error(self, msg): | 168 def Error(self, msg): |
| 151 print >> sys.stderr, 'ERROR: %s' % msg | 169 print >> sys.stderr, 'ERROR: %s' % msg |
| 152 | 170 |
| 153 def Fatal(self, msg=None): | 171 def Fatal(self, msg=None): |
| 154 if msg: | 172 if msg: |
| 155 self.Error(msg) | 173 self.Error(msg) |
| 156 sys.exit(1) | 174 sys.exit(1) |
| 157 | 175 |
| 158 def Info(self, msg): | 176 def Info(self, msg): |
| 159 if self.verbose: | 177 if self.verbose >= CrosEnv.INFO: |
| 160 print 'INFO: %s' % msg | 178 print 'INFO: %s' % msg |
| 161 | 179 |
| 180 def Debug(self, msg): |
| 181 if self.verbose >= CrosEnv.DEBUG: |
| 182 print 'DEBUG: %s' % msg |
| 183 |
| 162 def CrosUtilsPath(self, filename): | 184 def CrosUtilsPath(self, filename): |
| 163 return os.path.join(self.cros_root, filename) | 185 return os.path.join(self.cros_root, filename) |
| 164 | 186 |
| 165 def ChrootPath(self, filename): | 187 def ChrootPath(self, filename): |
| 166 return self.CrosUtilsPath(os.path.join('..', '..', 'chroot', | 188 return self.CrosUtilsPath(os.path.join('..', '..', 'chroot', |
| 167 filename.strip(os.path.sep))) | 189 filename.strip(os.path.sep))) |
| 168 | 190 |
| 169 def FileOneLine(self, filename): | 191 def FileOneLine(self, filename): |
| 170 return file(filename).read().rstrip('\r\n') | 192 return file(filename).read().rstrip('\r\n') |
| 171 | 193 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 248 def CreateServer(self, port, update_file, stateful_file): | 270 def CreateServer(self, port, update_file, stateful_file): |
| 249 """Start the devserver clone.""" | 271 """Start the devserver clone.""" |
| 250 | 272 |
| 251 PingUpdateResponse.Setup(self.GetHash(update_file), | 273 PingUpdateResponse.Setup(self.GetHash(update_file), |
| 252 self.GetSha256(update_file), | 274 self.GetSha256(update_file), |
| 253 self.GetSize(update_file)) | 275 self.GetSize(update_file)) |
| 254 | 276 |
| 255 UpdateHandler.SetupUrl('/update', PingUpdateResponse()) | 277 UpdateHandler.SetupUrl('/update', PingUpdateResponse()) |
| 256 UpdateHandler.SetupUrl('/%s' % UPDATE_FILENAME, | 278 UpdateHandler.SetupUrl('/%s' % UPDATE_FILENAME, |
| 257 FileUpdateResponse(update_file, | 279 FileUpdateResponse(update_file, |
| 258 verbose=self.verbose)) | 280 verbose=self.verbose, |
| 281 have_pv=self.have_pv)) |
| 259 UpdateHandler.SetupUrl('/%s' % STATEFUL_FILENAME, | 282 UpdateHandler.SetupUrl('/%s' % STATEFUL_FILENAME, |
| 260 FileUpdateResponse(stateful_file, | 283 FileUpdateResponse(stateful_file, |
| 261 verbose=self.verbose)) | 284 verbose=self.verbose, |
| 285 have_pv=self.have_pv)) |
| 262 | 286 |
| 263 self.http_server = BaseHTTPServer.HTTPServer(('', port), UpdateHandler) | 287 self.http_server = BaseHTTPServer.HTTPServer(('', port), UpdateHandler) |
| 264 | 288 |
| 265 def StartServer(self): | 289 def StartServer(self): |
| 266 self.Info('Starting http server') | 290 self.Info('Starting http server') |
| 267 self.http_server.serve_forever() | 291 self.http_server.serve_forever() |
| 268 | 292 |
| 269 def GetUpdateStatus(self): | 293 def GetUpdateStatus(self): |
| 270 status = self.ssh_cmd.Output('/usr/bin/update_engine_client', '--status') | 294 status = self.ssh_cmd.Output('/usr/bin/update_engine_client', '--status') |
| 271 if not status: | 295 if not status: |
| (...skipping 18 matching lines...) Expand all Loading... |
| 290 self.Info('Client has not yet restarted (try %d). Waiting...' % attempt) | 314 self.Info('Client has not yet restarted (try %d). Waiting...' % attempt) |
| 291 wait_time = SSHCommand.CONNECT_TIMEOUT - (time.time() - start) | 315 wait_time = SSHCommand.CONNECT_TIMEOUT - (time.time() - start) |
| 292 if wait_time > 0: | 316 if wait_time > 0: |
| 293 time.sleep(wait_time) | 317 time.sleep(wait_time) |
| 294 | 318 |
| 295 return False | 319 return False |
| 296 | 320 |
| 297 def StartClient(self, port): | 321 def StartClient(self, port): |
| 298 """Ask the client machine to update from our server.""" | 322 """Ask the client machine to update from our server.""" |
| 299 | 323 |
| 324 self.Info("Starting client...") |
| 300 status = self.GetUpdateStatus() | 325 status = self.GetUpdateStatus() |
| 301 if status != 'UPDATE_STATUS_IDLE': | 326 if status != 'UPDATE_STATUS_IDLE': |
| 302 self.Error('Client update status is not IDLE: %s' % status) | 327 self.Error('Client update status is not IDLE: %s' % status) |
| 303 return False | 328 return False |
| 304 | 329 |
| 305 url_base = 'http://localhost:%d' % port | 330 url_base = 'http://localhost:%d' % port |
| 306 update_url = '%s/update' % url_base | 331 update_url = '%s/update' % url_base |
| 307 fd, update_log = tempfile.mkstemp(prefix='image-to-target-') | 332 fd, update_log = tempfile.mkstemp(prefix='image-to-target-') |
| 308 self.Info('Starting update on client. Client output stored to %s' % | 333 self.Info('Starting update on client. Client output stored to %s' % |
| 309 update_log) | 334 update_log) |
| 335 |
| 336 # this will make the client read the files we have set up |
| 310 self.ssh_cmd.Run('/usr/bin/update_engine_client', '--update', | 337 self.ssh_cmd.Run('/usr/bin/update_engine_client', '--update', |
| 311 '--omaha_url', update_url, remote_tunnel=(port, port), | 338 '--omaha_url', update_url, remote_tunnel=(port, port), |
| 312 outfile=update_log) | 339 outfile=update_log) |
| 313 | 340 |
| 314 if self.GetUpdateStatus() != 'UPDATE_STATUS_UPDATED_NEED_REBOOT': | 341 if self.GetUpdateStatus() != 'UPDATE_STATUS_UPDATED_NEED_REBOOT': |
| 315 self.Error('Client update failed') | 342 self.Error('Client update failed') |
| 316 return False | 343 return False |
| 317 | 344 |
| 345 self.Info('Update complete - running update script on client') |
| 318 self.ssh_cmd.Copy(self.CrosUtilsPath('../platform/dev/stateful_update'), | 346 self.ssh_cmd.Copy(self.CrosUtilsPath('../platform/dev/stateful_update'), |
| 319 '/tmp') | 347 '/tmp') |
| 320 if not self.ssh_cmd.Run('/tmp/stateful_update', url_base, | 348 if not self.ssh_cmd.Run('/tmp/stateful_update', url_base, |
| 321 remote_tunnel=(port, port)): | 349 remote_tunnel=(port, port)): |
| 322 self.Error('Client stateful update failed') | 350 self.Error('Client stateful update failed') |
| 323 return False | 351 return False |
| 324 | 352 |
| 325 self.Info('Rebooting client') | 353 self.Info('Rebooting client') |
| 326 if not self.ClientReboot(): | 354 if not self.ClientReboot(): |
| 327 self.Error('Client may not have successfully rebooted...') | 355 self.Error('Client may not have successfully rebooted...') |
| 328 return False | 356 return False |
| 329 | 357 |
| 330 print 'Client update completed successfully!' | 358 self.Info('Client update completed successfully!') |
| 331 return True | 359 return True |
| 332 | 360 |
| 333 | 361 |
| 334 class UpdateResponse(object): | 362 class UpdateResponse(object): |
| 335 """Default response is the 404 error response.""" | 363 """Default response is the 404 error response.""" |
| 336 | 364 |
| 337 def Reply(self, handler, send_content=True, post_data=None): | 365 def Reply(self, handler, send_content=True, post_data=None): |
| 338 handler.send_Error(404, 'File not found') | 366 handler.send_error(404, 'File not found') |
| 339 return None | 367 return None |
| 340 | 368 |
| 341 | 369 |
| 342 class FileUpdateResponse(UpdateResponse): | 370 class FileUpdateResponse(UpdateResponse): |
| 343 """Respond by sending the contents of a file.""" | 371 """Respond by sending the contents of a file.""" |
| 344 | 372 |
| 345 def __init__(self, filename, content_type='application/octet-stream', | 373 def __init__(self, filename, content_type='application/octet-stream', |
| 346 verbose=False, blocksize=16*1024): | 374 verbose=False, blocksize=16*1024, have_pv=False): |
| 347 self.filename = filename | 375 self.filename = filename |
| 348 self.content_type = content_type | 376 self.content_type = content_type |
| 349 self.verbose = verbose | 377 self.verbose = verbose |
| 350 self.blocksize = blocksize | 378 self.blocksize = blocksize |
| 379 self.have_pv = have_pv |
| 351 | 380 |
| 352 def Reply(self, handler, send_content=True, post_data=None): | 381 def Reply(self, handler, send_content=True, post_data=None): |
| 353 """Return file contents to the client. Optionally display progress.""" | 382 """Return file contents to the client. Optionally display progress.""" |
| 354 | 383 |
| 355 try: | 384 try: |
| 356 f = open(self.filename, 'rb') | 385 f = open(self.filename, 'rb') |
| 357 except IOError: | 386 except IOError: |
| 358 return UpdateResponse.Reply(self, handler) | 387 return UpdateResponse.Reply(self, handler) |
| 359 | 388 |
| 360 handler.send_response(200) | 389 handler.send_response(200) |
| 361 handler.send_header('Content-type', self.content_type) | 390 handler.send_header('Content-type', self.content_type) |
| 362 filestat = os.fstat(f.fileno()) | 391 filestat = os.fstat(f.fileno()) |
| 363 filesize = filestat[6] | 392 filesize = filestat[6] |
| 364 handler.send_header('Content-Length', str(filesize)) | 393 handler.send_header('Content-Length', str(filesize)) |
| 365 handler.send_header('Last-Modified', | 394 handler.send_header('Last-Modified', |
| 366 handler.date_time_string(filestat.st_mtime)) | 395 handler.date_time_string(filestat.st_mtime)) |
| 367 handler.end_headers() | 396 handler.end_headers() |
| 368 | 397 |
| 369 if not send_content: | 398 if send_content: |
| 370 return | |
| 371 | |
| 372 if filesize <= self.blocksize: | |
| 373 handler.wfile.write(f.read()) | |
| 374 else: | |
| 375 sent_size = 0 | 399 sent_size = 0 |
| 376 sent_percentage = None | 400 sent_percentage = None |
| 401 |
| 402 #TODO(sjg): this should use pv also |
| 377 while True: | 403 while True: |
| 378 buf = f.read(self.blocksize) | 404 buf = f.read(self.blocksize) |
| 379 if not buf: | 405 if not buf: |
| 380 break | 406 break |
| 381 handler.wfile.write(buf) | 407 handler.wfile.write(buf) |
| 382 if self.verbose: | 408 if self.verbose: |
| 383 sent_size += len(buf) | 409 sent_size += len(buf) |
| 384 percentage = int(100 * sent_size / filesize) | 410 percentage = int(100 * sent_size / filesize) |
| 385 if sent_percentage != percentage: | 411 if sent_percentage != percentage: |
| 386 sent_percentage = percentage | 412 sent_percentage = percentage |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 542 usage = 'usage: %prog [options]' | 568 usage = 'usage: %prog [options]' |
| 543 parser = optparse.OptionParser(usage=usage) | 569 parser = optparse.OptionParser(usage=usage) |
| 544 parser.add_option('--board', dest='board', default=None, | 570 parser.add_option('--board', dest='board', default=None, |
| 545 help='Board platform type') | 571 help='Board platform type') |
| 546 parser.add_option('--force-mismatch', dest='force_mismatch', default=False, | 572 parser.add_option('--force-mismatch', dest='force_mismatch', default=False, |
| 547 action='store_true', | 573 action='store_true', |
| 548 help='Upgrade even if client arch does not match') | 574 help='Upgrade even if client arch does not match') |
| 549 parser.add_option('--from', dest='src', default=None, | 575 parser.add_option('--from', dest='src', default=None, |
| 550 help='Source image to install') | 576 help='Source image to install') |
| 551 parser.add_option('--image-name', dest='image_name', | 577 parser.add_option('--image-name', dest='image_name', |
| 552 default=DEFAULT_IMAGE_NAME, | |
| 553 help='Filename within image directory to load') | 578 help='Filename within image directory to load') |
| 554 parser.add_option('--port', dest='port', default=8081, type='int', | 579 parser.add_option('--port', dest='port', default=8081, type='int', |
| 555 help='TCP port to serve from and tunnel through') | 580 help='TCP port to serve from and tunnel through') |
| 556 parser.add_option('--remote', dest='remote', default=None, | 581 parser.add_option('--remote', dest='remote', default=None, |
| 557 help='Remote device-under-test IP address') | 582 help='Remote device-under-test IP address') |
| 558 parser.add_option('--server-only', dest='server_only', default=False, | 583 parser.add_option('--server-only', dest='server_only', default=False, |
| 559 action='store_true', help='Do not start client') | 584 action='store_true', help='Do not start client') |
| 560 parser.add_option('--verbose', dest='verbose', default=False, | 585 parser.add_option('--verbose', dest='verbose', default=False, |
| 586 action='store_true', help='Display progress') |
| 587 parser.add_option('--debug', dest='debug', default=False, |
| 561 action='store_true', help='Display running commands') | 588 action='store_true', help='Display running commands') |
| 589 parser.add_option('--test', dest='test', default=False, |
| 590 action='store_true', help='Select test image') |
| 562 | 591 |
| 563 (options, args) = parser.parse_args(argv) | 592 (options, args) = parser.parse_args(argv) |
| 564 | 593 |
| 565 cros_env = CrosEnv(verbose=options.verbose) | 594 # we can build the test image if it doesn't exist, so remember if we want to |
| 595 build_test_image = False |
| 596 |
| 597 verbosity = CrosEnv.SILENT |
| 598 if options.verbose: |
| 599 verbosity = CrosEnv.INFO |
| 600 if options.debug: |
| 601 verbosity = CrosEnv.DEBUG |
| 602 cros_env = CrosEnv(verbose=verbosity) |
| 566 | 603 |
| 567 if not options.board: | 604 if not options.board: |
| 568 options.board = cros_env.GetDefaultBoard() | 605 options.board = cros_env.GetDefaultBoard() |
| 569 | 606 |
| 570 if not options.src: | 607 if not options.src: |
| 571 options.src = cros_env.GetLatestImage(options.board) | 608 options.src = cros_env.GetLatestImage(options.board) |
| 572 if options.src is None: | 609 if options.src is None: |
| 573 parser.error('No --from argument given and no default image found') | 610 parser.error('No --from argument given and no default image found') |
| 574 | 611 |
| 575 cros_env.Info('Performing update from %s' % options.src) | 612 cros_env.Info('Performing update from %s' % options.src) |
| 576 | 613 |
| 577 if not os.path.exists(options.src): | 614 if not os.path.exists(options.src): |
| 578 parser.error('Path %s does not exist' % options.src) | 615 parser.error('Path %s does not exist' % options.src) |
| 579 | 616 |
| 617 if not options.image_name: |
| 618 # auto-select the correct image |
| 619 if options.test: |
| 620 options.image_name = DEFAULT_IMAGE_NAME_TEST |
| 621 |
| 622 # we will build the test image if not found |
| 623 build_test_image = True |
| 624 else: |
| 625 options.image_name = DEFAULT_IMAGE_NAME |
| 626 |
| 580 if os.path.isdir(options.src): | 627 if os.path.isdir(options.src): |
| 581 image_directory = options.src | 628 image_directory = options.src |
| 582 image_file = os.path.join(options.src, options.image_name) | 629 image_file = os.path.join(options.src, options.image_name) |
| 583 | 630 |
| 584 if not os.path.exists(image_file): | 631 if not os.path.exists(image_file): |
| 632 if build_test_image: |
| 633 # we want a test image but it doesn't exist |
| 634 # try to build it if we can |
| 635 cros_env.Info('Creating test image') |
| 636 test_output = cros_env.cmd.Output( |
| 637 cros_env.CrosUtilsPath('enter_chroot.sh'), |
| 638 '--', './mod_image_for_test.sh', |
| 639 '--board=%s' % options.board, '-y') |
| 640 if not os.path.exists(image_file): |
| 641 print test_output |
| 642 cros_env.Fatal('Failed to create test image - please run ' |
| 643 './mod_image_for_test.sh manually inside the chroot') |
| 585 parser.error('Image file %s does not exist' % image_file) | 644 parser.error('Image file %s does not exist' % image_file) |
| 586 else: | 645 else: |
| 587 image_file = options.src | 646 image_file = options.src |
| 588 image_directory = os.path.dirname(options.src) | 647 image_directory = os.path.dirname(options.src) |
| 589 | 648 |
| 649 update_file = os.path.join(image_directory, UPDATE_FILENAME) |
| 650 stateful_file = os.path.join(image_directory, STATEFUL_FILENAME) |
| 651 |
| 652 cros_env.Debug("Image file %s" % image_file) |
| 653 cros_env.Debug("Update file %s" % update_file) |
| 654 cros_env.Debug("Stateful file %s" % stateful_file) |
| 655 |
| 590 if options.remote: | 656 if options.remote: |
| 657 cros_env.Info('Contacting client %s' % options.remote) |
| 591 cros_env.SetRemote(options.remote) | 658 cros_env.SetRemote(options.remote) |
| 592 rel = cros_env.GetRemoteRelease() | 659 rel = cros_env.GetRemoteRelease() |
| 593 if not rel: | 660 if not rel: |
| 594 cros_env.Fatal('Could not retrieve remote lsb-release') | 661 cros_env.Fatal('Could not retrieve remote lsb-release') |
| 595 board = rel.get('CHROMEOS_RELEASE_BOARD', '(None)') | 662 board = rel.get('CHROMEOS_RELEASE_BOARD', '(None)') |
| 596 if board != options.board and not options.force_mismatch: | 663 if board != options.board and not options.force_mismatch: |
| 597 cros_env.Error('Board %s does not match expected %s' % | 664 cros_env.Error('Board %s does not match expected %s' % |
| 598 (board, options.board)) | 665 (board, options.board)) |
| 599 cros_env.Error('(Use --force-mismatch option to override this)') | 666 cros_env.Error('(Use --force-mismatch option to override this)') |
| 600 cros_env.Fatal() | 667 cros_env.Fatal() |
| 601 | 668 |
| 602 elif not options.server_only: | 669 elif not options.server_only: |
| 603 parser.error('Either --server-only must be specified or ' | 670 parser.error('Either --server-only must be specified or ' |
| 604 '--remote=<client> needs to be given') | 671 '--remote=<client> needs to be given') |
| 605 | 672 |
| 606 update_file = os.path.join(image_directory, UPDATE_FILENAME) | |
| 607 stateful_file = os.path.join(image_directory, STATEFUL_FILENAME) | |
| 608 | |
| 609 if (not cros_env.GenerateUpdatePayload(image_file, update_file) or | 673 if (not cros_env.GenerateUpdatePayload(image_file, update_file) or |
| 610 not cros_env.BuildStateful(image_file, image_directory, stateful_file)): | 674 not cros_env.BuildStateful(image_file, image_directory, stateful_file)): |
| 611 cros_env.Fatal() | 675 cros_env.Fatal() |
| 612 | 676 |
| 613 cros_env.CreateServer(options.port, update_file, stateful_file) | 677 cros_env.CreateServer(options.port, update_file, stateful_file) |
| 614 | 678 |
| 615 exit_status = 1 | 679 exit_status = 1 |
| 616 if options.server_only: | 680 if options.server_only: |
| 617 child = None | 681 child = None |
| 618 else: | 682 else: |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 650 | 714 |
| 651 if child: | 715 if child: |
| 652 os.kill(child, 15) | 716 os.kill(child, 15) |
| 653 | 717 |
| 654 cros_env.Info('Server exiting with status %d' % exit_status) | 718 cros_env.Info('Server exiting with status %d' % exit_status) |
| 655 sys.exit(exit_status) | 719 sys.exit(exit_status) |
| 656 | 720 |
| 657 | 721 |
| 658 if __name__ == '__main__': | 722 if __name__ == '__main__': |
| 659 main(sys.argv) | 723 main(sys.argv) |
| OLD | NEW |