Example #1
0
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()
Example #2
0
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()
Example #3
0
    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')
Example #4
0
    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')
Example #5
0
    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()
Example #6
0
    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")
Example #7
0
    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")
Example #8
0
    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)
Example #10
0
    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)