def _retrieve_tarball(self, ctx): ''' Retrieve tarball for a given version ''' # TODO make this function more robust wrt unexpected errors if not 'result' in ctx: logging.error('updater_runner: no result') self._schedule() return length, body, error = ctx.pop('result') if length == -1: logging.error('updater_runner: error: %s', str(error)) self._schedule() return sha256 = updater_utils.sha256sum_extract(ctx['vinfo'], body) if not sha256: logging.error('updater_runner: invalid sha256') self._schedule() return # XXX We should not reuse the same CTX here ctx['sha256'] = sha256 ctx['uri'] = updater_utils.tarball_get_uri(self.channel, ctx['vinfo']) RUNNER_CORE.run('dload', self._process_files, False, ctx)
def _retrieve_tarball(self, ctx): ''' Retrieve tarball for a given version ''' if not 'result' in ctx: logging.error('updater_runner: no result') self._schedule() return length, body, error = ctx.pop('result') if length == -1: logging.info('updater_runner: %s', str(error)) self._schedule() return logging.info('updater_runner: signature (base64): %s', base64.b64encode(body)) ctx['signature'] = body ctx['uri'] = updater_utils.tarball_get_uri(self.system, ctx['vinfo']) logging.info('updater_runner: GET %s', ctx['uri']) deferred = Deferred() deferred.add_callback(self._process_files) deferred.add_errback(self._handle_failure) RUNNER_CORE.run('dload', deferred, False, ctx)
def run(self): ''' Periodically run rendezvous ''' logging.info('background_rendezvous: automatic rendezvous...') deferred = Deferred() deferred.add_callback(self._after_rendezvous) deferred.add_errback(self._schedule) RUNNER_CORE.run('rendezvous', deferred, False, None)
def run(self): ''' Periodically run rendezvous ''' if not privacy.allowed_to_run(): _open_browser_on_windows('privacy.html') # Except from opening the browser, privacy actions are # now performed by RUNNER_CORE RUNNER_CORE.run('rendezvous', self._after_rendezvous)
def run(self): ''' Periodically run rendezvous ''' # # Except from opening the browser, privacy actions are # now performed by RUNNER_CORE # if not privacy.allowed_to_run(): self._open_browser_on_windows('privacy.html') logging.info('background_rendezvous: automatic rendezvous...') RUNNER_CORE.run('rendezvous', self._after_rendezvous)
def run(self): ''' Periodically run rendezvous ''' # # Except from opening the browser, privacy actions are # now performed by RUNNER_CORE # if not privacy.allowed_to_run(): self._open_browser_on_windows('privacy.html') logging.info('background_rendezvous: automatic rendezvous...') deferred = Deferred() deferred.add_callback(self._after_rendezvous) deferred.add_errback(self._schedule) RUNNER_CORE.run('rendezvous', deferred, False, None)
def _after_rendezvous(self, unused): ''' After rendezvous actions ''' # # This function is invoked both when the rendezvous fails # and succeeds. If it succeeds, OK we have fresh information # on available tests and updates and we use it. Otherwise, # if rendezvous fails, we may either have old information, or # no information, if this is the first rendezvous. In any # case, we do our best to use the available information. # logging.info('background_rendezvous: automatic rendezvous... done') # Inform the user when we have updates new_version = RUNNER_UPDATES.get_update_version() new_uri = RUNNER_UPDATES.get_update_uri() if new_version and new_uri and not CONFIG['win32_updater']: logging.info('runner_rendezvous: version %s available at %s', new_version, new_uri) STATE.update('update', {'version': new_version, 'uri': new_uri}) self._open_browser_on_windows('update.html') # # Choose the test we would like to run even if # we're not going to run it because tests are # disabled. So we can print the test name also # when tests are disabled. # test = RUNNER_POLICY.get_next_test() logging.info('background_rendezvous: chosen test: %s', test) # Are we allowed to run a test? if not CONFIG['enabled']: raise RuntimeError('background_rendezvous: automatic ' 'tests disabled') # # RAW test requires auto_discover to be True, since it uses mlab-ns # to discover servers. Other tests don't need that, since, at the # moment, they discover servers during the rendezvous. So, if their # auto_discover were True, they'd end up running two rendezvous in # a row for no good reason. # auto_discover = (test == 'raw') # Actually run the test deferred = Deferred() deferred.add_callback(self._schedule) RUNNER_CORE.run(test, deferred, auto_discover, None)
def retrieve_files(self, ctx, vinfo): ''' Retrieve files for a given version ''' # Note: this is a separate function for testability uri = updater_utils.signature_get_uri(self.system, vinfo) ctx['uri'] = uri ctx['vinfo'] = vinfo logging.info('updater_runner: GET %s', uri) deferred = Deferred() deferred.add_callback(self._retrieve_tarball) deferred.add_errback(self._handle_failure) RUNNER_CORE.run('dload', deferred, False, ctx)
def retrieve_versioninfo(self): ''' Retrieve version information ''' # # The windows updater is still experimental, so it # is disabled by default and one needs to enable it # explicitly using the Web UI. # if not CONFIG['win32_updater']: self._schedule() return ctx = { 'uri': updater_utils.versioninfo_get_uri(self.channel) } RUNNER_CORE.run('dload', self._process_versioninfo, False, ctx)
def _after_rendezvous(self, unused): ''' After rendezvous actions ''' # # This function is invoked both when the rendezvous fails # and succeeds. If it succeeds, OK we have fresh information # on available tests and updates and we use it. Otherwise, # if rendezvous fails, we may either have old information, or # no information, if this is the first rendezvous. In any # case, we do our best to use the available information. # logging.info('background_rendezvous: automatic rendezvous... done') # Inform the user when we have updates new_version = RUNNER_UPDATES.get_update_version() new_uri = RUNNER_UPDATES.get_update_uri() if new_version and new_uri and not CONFIG['win32_updater']: logging.info('runner_rendezvous: version %s available at %s', new_version, new_uri) STATE.update('update', {'version': new_version, 'uri': new_uri}) # # Choose the test we would like to run even if # we're not going to run it because tests are # disabled. So we can print the test name also # when tests are disabled. # # Note: we pick a test at random because now we # have a fixed probability of running a test. # test = RUNNER_POLICY.get_random_test() logging.info('background_rendezvous: chosen test: %s', test) # Are we allowed to run a test? if not CONFIG['enabled']: raise RuntimeError('background_rendezvous: automatic ' 'tests disabled') # # The two legacy tests, speedtest and bittorent, use the rendezvous # to discover the servers. Other tests use mlab-ns. # use_mlabns = (test != 'speedtest' and test != 'bittorrent') # Actually run the test deferred = Deferred() deferred.add_callback(self._schedule) RUNNER_CORE.run(test, deferred, use_mlabns, None)
def _after_rendezvous(self): ''' After rendezvous actions ''' # TODO Make this function more robust wrt unexpected errors # # This function is invoked both when the rendezvous fails # and succeeds. If it succeeds, OK we have fresh information # on available tests and updates and we use it. Otherwise, # if rendezvous fails, we may either have old information, or # no information, if this is the first rendezvous. In any # case, we do our best to use the available information. # logging.info('background_rendezvous: automatic rendezvous... done') # Inform the user when we have updates new_version = RUNNER_UPDATES.get_update_version() new_uri = RUNNER_UPDATES.get_update_uri() if new_version and new_uri and not CONFIG['win32_updater']: logging.info('runner_rendezvous: version %s available at %s', new_version, new_uri) STATE.update('update', {'version': new_version, 'uri': new_uri}) self._open_browser_on_windows('update.html') # # Choose the test we would like to run even if # we're not going to run it because tests are # disabled. So we can print the test name also # when tests are disabled. # test = RUNNER_TESTS.get_next_test() if not test: logging.warning('background_rendezvous: no test available') self._schedule() return logging.info('background_rendezvous: chosen test: %s', test) # Are we allowed to run a test? if not CONFIG['enabled']: logging.info('background_rendezvous: automatic tests are disabled') self._schedule() return # Actually run the test RUNNER_CORE.run(test, self._schedule)
def _after_rendezvous(self): ''' After rendezvous actions ''' # # If rendezvous fails, RUNNER_UPDATES and RUNNER_TESTS # may be empty. In such case, this function becomes just # a no operation and nothing happens. # # Inform the user when we have updates new_version = RUNNER_UPDATES.get_update_version() new_uri = RUNNER_UPDATES.get_update_uri() if new_version and new_uri: logging.info("Version %s available at %s", new_version, new_uri) STATE.update("update", {"version": new_version, "uri": new_uri}) _open_browser_on_windows('update.html') # # Choose the test we would like to run even if # we're not going to run it because we're running # in debug mode or tests are disabled. # This allows us to print to the logger the test # we /would/ have choosen if we were allowed to # run tests. # test = RUNNER_TESTS.get_next_test() if not test: logging.warning("No test available") self._schedule() return logging.info("* Chosen test: %s", test) # Are we allowed to run a test? if not CONFIG["enabled"]: logging.info("Tests are disabled... not running") self._schedule() return # Actually run the test RUNNER_CORE.run(test, self._schedule)
def retrieve_versioninfo(self): ''' Retrieve version information ''' # # The windows updater is still experimental, so it # is disabled by default and one needs to enable it # explicitly using the Web UI. # if not CONFIG['win32_updater']: self._schedule() return channel = CONFIG['win32_updater_channel'] ctx = { 'uri': updater_utils.versioninfo_get_uri(self.system, channel) } deferred = Deferred() deferred.add_callback(self._process_versioninfo) deferred.add_errback(self._handle_failure) RUNNER_CORE.run('dload', deferred, False, ctx)
def runner_api(stream, request, query): ''' Implements /api/runner ''' response = Message() # # DO NOT allow to start a test when another test is in # progress because I have noticed that is confusing both # from # command line and WUI. # if RUNNER_CORE.test_is_running(): raise ConfigError('A test is already in progress, try again later') # # If there is not a query string this API is just # a no-operation and returns an empty JSON body to # keep happy the AJAX code. # if not query: response.compose(code='200', reason='Ok', body='{}', mimetype='application/json') stream.send_response(request, response) return options = cgi.parse_qs(query) # # If the query does not contain the name of the # test, this is an error and we must notify that # to the caller. Raise ConfigError, which will # be automatically transformed into a 500 message # with the proper body and reason. # if not 'test' in options: raise ConfigError('Missing "test" option in query string') test = options['test'][0] # # Simple case: the caller does not want to follow the # test via log streaming. We can immediately start # the test using the runner and, if everything is OK, # we can send a succesful response, with an empty JSON # body to keep happy the AJAX code. # if not 'streaming' in options or not utils.intify(options['streaming'][0]): RUNNER_CORE.run(test, runner_api_done) response.compose(code='200', reason='Ok', body='{}', mimetype='application/json') stream.send_response(request, response) return # # More interesting case: the caller wants to see the log # messages during the test via the log streaming API. # We prepare a succesful response terminated by EOF and # then arrange things so that every new log message will # be copied to the HTTP response. # Then we kick off the runner, and note that we do that # AFTER we setup the response for eventual runner errors # to be copied to the HTTP response. # The runner core will automatically close all attached # streams at the end of the test. # response.compose(code='200', reason='Ok', up_to_eof=True, mimetype='text/plain') stream.send_response(request, response) LOG.start_streaming(stream) RUNNER_CORE.run(test, runner_api_done)
def retrieve_files(self, vinfo): ''' Retrieve files for a given version ''' # Note: this is a separate function for testability uri = updater_utils.sha256sum_get_uri(self.channel, vinfo) ctx = {'vinfo': vinfo, 'uri': uri} RUNNER_CORE.run('dload', self._retrieve_tarball, False, ctx)