def main(args): ''' Main function ''' try: options, arguments = getopt.getopt(args[1:], 'f:nv') except getopt.error: sys.exit(USAGE) database_path = system.get_default_database_path() auto_discover = True for name, value in options: if name == '-f': database_path = value elif name == '-n': auto_discover = False elif name == '-v': CONFIG['verbose'] = 1 if len(arguments) != 1 and len(arguments) != 2: sys.exit(USAGE) DATABASE.set_path(database_path) CONFIG.merge_database(DATABASE.connection()) if len(arguments) == 2: RUNNER_TESTS.update({arguments[0]: [arguments[1]]}) ctx = {'uri': arguments[1]} else: ctx = None deferred = Deferred() deferred.add_callback(lambda param: None) RUNNER_CORE.run(arguments[0], deferred, auto_discover, ctx) POLLER.loop()
def main(args): ''' Main function ''' try: options, arguments = getopt.getopt(args[1:], 'f:n') except getopt.error: sys.exit('Usage: %s [-n] [-f database] test [negotiate_uri]' % args[0]) if len(arguments) != 1 and len(arguments) != 2: sys.exit('Usage: %s [-n] [-f database] test [negotiate_uri]' % args[0]) database_path = system.get_default_database_path() auto_rendezvous = True for name, value in options: if name == '-f': database_path = value elif name == '-n': auto_rendezvous = False DATABASE.set_path(database_path) CONFIG.merge_database(DATABASE.connection()) if len(arguments) == 2: RUNNER_TESTS.update({arguments[0]: [arguments[1]]}) ctx = {'uri': arguments[1]} else: ctx = None RUNNER_CORE.run(arguments[0], lambda *args: None, auto_rendezvous, ctx) POLLER.loop()
def _do_run_queue(self, first_elem): ''' Actually run first element in queue ''' # Make a copy of current settings conf = CONFIG.copy() # Make sure we abide to M-Lab policy if privacy.count_valid(conf, 'privacy.') != 3: privacy.complain() raise RuntimeError('runner_core: bad privacy settings') elif first_elem[0] == 'rendezvous': runner_rendezvous.run(conf['agent.master'], '9773') elif first_elem[0] == 'speedtest': uri = RUNNER_TESTS.test_to_negotiate_uri('speedtest') conf['speedtest.client.uri'] = uri client = ClientSpeedtest(POLLER) client.configure(conf) client.connect_uri() elif first_elem[0] == 'bittorrent': uri = RUNNER_TESTS.test_to_negotiate_uri('bittorrent') conf['bittorrent._uri'] = uri bittorrent.run(POLLER, conf) elif first_elem[0] == 'dload': RunnerDload(first_elem[2]) elif first_elem[0] == 'raw': address = RUNNER_HOSTS.get_random_host() handler = RawNegotiate() handler.connect((address, 8080), CONFIG['prefer_ipv6'], 0, {}) elif first_elem[0] == 'mlab-ns': handler = RunnerMlabns() if not first_elem[2]: extra = {'policy': ''} # get closest server by default else: extra = first_elem[2] handler.connect(('mlab-ns.appspot.com', 80), CONFIG['prefer_ipv6'], 0, extra) elif first_elem[0] in self.dynamic_tests: address = RUNNER_HOSTS.get_random_host() port = 80 # XXX self.dynamic_tests[first_elem[0]]["test_func"]({ "address": address, "conf": CONFIG.copy(), "poller": POLLER, "port": port, }) else: raise RuntimeError('runner_core: asked to run an unknown test')
def _do_run_queue(self): ''' Actually run first element in queue ''' # Make a copy of current settings conf = CONFIG.copy() # Make sure we abide to M-Lab policy if privacy.count_valid(conf, 'privacy.') != 3: privacy.complain() raise RuntimeError('Bad privacy settings') # Run rendezvous elif self.queue[0][0] == 'rendezvous': uri = "http://%s:9773/rendezvous" % conf['agent.master'] runner_rendezvous.run(uri) # Run speedtest elif self.queue[0][0] == 'speedtest': uri = RUNNER_TESTS.test_to_negotiate_uri('speedtest') # # If we have no negotiate URI for this test, possibly # because we are offline, abort it. # if not uri: raise RuntimeError('No negotiate URI for speedtest') conf['speedtest.client.uri'] = uri client = ClientSpeedtest(POLLER) client.configure(conf) client.connect_uri() # Run bittorrent elif self.queue[0][0] == 'bittorrent': uri = RUNNER_TESTS.test_to_negotiate_uri('bittorrent') # # If we have no negotiate URI for this test, possibly # because we are offline, abort it. # if not uri: raise RuntimeError('No negotiate URI for bittorrent') conf['bittorrent._uri'] = uri bittorrent.run(POLLER, conf) # Run dload elif self.queue[0][0] == 'dload': RunnerDload(self.queue[0][2]) # Safety net else: raise RuntimeError('Asked to run an unknown test')
def got_response(self, stream, request, response): ''' Invoked when the response is received ''' if response.code != '200': logging.info('runner_rendezvous: bad response') stream.close() return message = json.load(response.body) RUNNER_TESTS.update(message['available']) RUNNER_UPDATES.update(message['update']) logging.info('runner_rendezvous: rendezvous complete') stream.close()
def test_bittorrent_invokation_good(self): ''' Verify run_queue() behavior when bittorrent is invoked and there is a URI for bittorrent ''' # # The whole point of this test is to make sure that # bittorrent.run() is invoked when privacy is OK and # we have a negotiate URI. We also want to check that # the "testdone" event is subscribed after run_queue(), # i.e. that someone is waiting for the event that # signals the end of the test. # # We need to ensure bittorrent.run() is invoked bittorrent_run = [0] def on_bittorrent_run(poller, conf): ''' Register bittorrent.run() invokation ''' # pylint: disable=W0613 bittorrent_run[0] += 1 # Setup (we will restore that later) saved_run = bittorrent.run bittorrent.run = on_bittorrent_run RUNNER_TESTS.update({'bittorrent': '/'}) CONFIG.conf['privacy.can_publish'] = 1 CONFIG.conf['privacy.informed'] = 1 CONFIG.conf['privacy.can_collect'] = 1 core = RunnerCore() core.queue.append(('bittorrent', Deferred(), None)) core.run_queue() # Restore bittorrent.run = saved_run RUNNER_TESTS.update({}) # Worked as expected? self.assertTrue(bittorrent_run[0]) self.assertTrue(NOTIFIER.is_subscribed("testdone")) # # Clear the "testdone" because otherwise it will # screw up other tests and we don't want that # NOTIFIER.publish("testdone")
def run(self, test, callback, auto_rendezvous=True, ctx=None): ''' Run test and callback() when done ''' # # If we are about to run a test and the list of # available tests is empty, we need certainly to # refill it before proceeding. # if (auto_rendezvous and test != 'rendezvous' and len(RUNNER_TESTS.get_test_names()) == 0): LOG.info('runner_core: Need to rendezvous first...') self.queue.append(('rendezvous', lambda: None, None)) self.queue.append((test, callback, ctx)) self.run_queue()
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)