Exemple #1
0
    def _authenticate(self, auth_kwargs):
        """
        Helper method to turn some auth_kwargs into a set of potential storage
        URLs and a token.
        """
        if auth_kwargs.get('token'):
            logging.debug('Using token %s at one of %r',
                          auth_kwargs['token'], auth_kwargs['storage_urls'])
            return auth_kwargs['storage_urls'], auth_kwargs['token']

        logging.debug('Authenticating to %s with %s/%s',
                      auth_kwargs['auth_url'], auth_kwargs['user'],
                      auth_kwargs['key'])
        storage_url, token = client.get_auth(**auth_kwargs)
        if auth_kwargs['storage_urls']:
            logging.debug('Overriding auth storage url %s with '
                          'one of %r', storage_url,
                          auth_kwargs['storage_urls'])
            return auth_kwargs['storage_urls'], token

        return [storage_url], token
Exemple #2
0
    def _authenticate(self, auth_kwargs):
        """
        Helper method to turn some auth_kwargs into a set of potential storage
        URLs and a token.
        """
        if auth_kwargs.get('token'):
            logging.debug('Using token %s at one of %r', auth_kwargs['token'],
                          auth_kwargs['storage_urls'])
            return auth_kwargs['storage_urls'], auth_kwargs['token']

        logging.debug('Authenticating to %s with %s/%s',
                      auth_kwargs['auth_url'], auth_kwargs['user'],
                      auth_kwargs['key'])
        storage_url, token = client.get_auth(**auth_kwargs)
        if auth_kwargs['storage_urls']:
            logging.debug('Overriding auth storage url %s with '
                          'one of %r', storage_url,
                          auth_kwargs['storage_urls'])
            return auth_kwargs['storage_urls'], token

        return [storage_url], token
Exemple #3
0
    def run_scenario(self, scenario, auth_url, user, key, auth_version,
                     os_options, cacert, insecure, storage_url, token,
                     noop=False, with_profiling=False, keep_objects=False,
                     batch_size=1):
        """
        Runs a CRUD scenario, given cluster parameters and a Scenario object.

        :param scenario: Scenario object describing the benchmark run
        :param auth_url: Authentication URL for the Swift cluster
        :param user: Account/Username to use (format is <account>:<username>)
        :param key: Password for the Account/Username
        :param auth_version: OpenStack auth version, default is 1.0
        :param os_options: The OpenStack options which can have tenant_id,
                           auth_token, service_type, endpoint_type,
                           tenant_name, object_storage_url, region_name
        :param insecure: Allow to access insecure keystone server.
                         The keystone's certificate will not be verified.
        :param cacert: Bundle file to use in verifying SSL.
        :param storage_url: Optional user-specified x-storage-url
        :param token: Optional user-specified x-auth-token
        :param noop: Run in no-op mode?
        :param with_profiing: Profile the run?
        :param keep_objects: Keep uploaded objects instead of deleting them?
        :param batch_size: Send this many bench jobs per packet to workers
        :param returns: Collected result records from workers
        """

        run_state = RunState()

        logging.info(u'Starting scenario run for "%s"', scenario.name)

        soft_nofile, hard_nofile = resource.getrlimit(resource.RLIMIT_NOFILE)
        nofile_target = 1024
        if os.geteuid() == 0:
            nofile_target = max(nofile_target, scenario.user_count + 20)
            hard_nofile = nofile_target
        resource.setrlimit(resource.RLIMIT_NOFILE, (nofile_target,
                                                    hard_nofile))

        # Construct auth_kwargs appropriate for client.get_auth()
        if not token:
            auth_kwargs = dict(
                auth_url=auth_url, user=user, key=key,
                auth_version=auth_version, os_options=os_options,
                cacert=cacert, insecure=insecure, storage_url=storage_url)
        else:
            auth_kwargs = dict(storage_url=storage_url, token=token)

        # Ensure containers exist
        if not noop:
            if not token:
                logging.debug('Authenticating to %s with %s/%s', auth_url,
                              user, key)
                c_storage_url, c_token = client.get_auth(**auth_kwargs)
                if storage_url:
                    logging.debug('Overriding auth storage url %s with %s',
                                  c_storage_url, storage_url)
                    c_storage_url = storage_url
            else:
                c_storage_url, c_token = storage_url, token
                logging.debug('Using token %s at %s', c_token, c_storage_url)

            logging.info('Ensuring %d containers (%s_*) exist; '
                         'concurrency=%d...',
                         len(scenario.containers), scenario.container_base,
                         scenario.container_concurrency)
            pool = gevent.pool.Pool(scenario.container_concurrency)
            for container in scenario.containers:
                pool.spawn(_container_creator, c_storage_url, c_token,
                           container)
            pool.join()

        # Enqueue initialization jobs
        if not noop:
            logging.info('Initializing cluster with stock data (up to %d '
                         'concurrent workers)', scenario.user_count)

            self.do_a_run(scenario.user_count, scenario.initial_jobs(),
                          run_state.handle_initialization_result, auth_kwargs,
                          batch_size=batch_size)

        logging.info('Starting benchmark run (up to %d concurrent '
                     'workers)', scenario.user_count)
        if noop:
            logging.info('  (not actually talking to Swift cluster!)')

        if with_profiling:
            import cProfile
            prof = cProfile.Profile()
            prof.enable()
        self.do_a_run(scenario.user_count, scenario.bench_jobs(),
                      run_state.handle_run_result, auth_kwargs,
                      mapper_fn=run_state.fill_in_job,
                      label='Benchmark Run:', noop=noop, batch_size=batch_size)
        if with_profiling:
            prof.disable()
            prof_output_path = '/tmp/do_a_run.%d.prof' % os.getpid()
            prof.dump_stats(prof_output_path)
            logging.info('PROFILED main do_a_run to %s', prof_output_path)

        if not noop and not keep_objects:
            logging.info('Deleting population objects from cluster')
            self.do_a_run(scenario.user_count,
                          run_state.cleanup_object_infos(),
                          lambda *_: None,
                          auth_kwargs, mapper_fn=_gen_cleanup_job,
                          batch_size=batch_size)
        elif keep_objects:
            logging.info('NOT deleting any objects due to -k/--keep-objects')

        return run_state.run_results
Exemple #4
0
    def ignoring_http_responses(self, statuses, fn, call_info, **extra_keys):
        if 401 not in statuses:
            statuses += (401, )
        args = dict(
            container=call_info['container'],
            name=call_info['name'],
        )
        args.update(extra_keys)

        if 'auth_kwargs' not in call_info:
            raise ValueError('Got benchmark job without "auth_kwargs" key!')

        tries = 0
        while True:
            # Make sure we've got a current storage_url/token
            if call_info['auth_kwargs'].get('token', None):
                token_key = None
                args['url'] = random.choice(
                    call_info['auth_kwargs']['storage_urls'])
                args['token'] = call_info['auth_kwargs']['token']
            else:
                token_key = self._token_key(call_info['auth_kwargs'])
                if token_key not in self.token_data:
                    self.token_data_lock.acquire()
                    collided = False
                    try:
                        if token_key not in self.token_data:
                            logging.debug('Authenticating with %r',
                                          call_info['auth_kwargs'])
                            storage_url, token = client.get_auth(
                                **call_info['auth_kwargs'])
                            override_urls = call_info['auth_kwargs'].get(
                                'storage_urls', None)
                            if override_urls:
                                logging.debug(
                                    'Will override auth storage url %s with '
                                    'one of %r', storage_url, override_urls)
                                storage_urls = override_urls
                            else:
                                storage_urls = [storage_url]
                            self.token_data[token_key] = (storage_urls, token)
                        else:
                            collided = True
                    finally:
                        self.token_data_lock.release()
                    if collided:
                        # Wait just a little bit if we just collided with
                        # another greenthread's re-auth
                        logging.debug('Collided on re-auth; sleeping 0.005')
                        gevent.sleep(0.005)
                storage_urls, args['token'] = self.token_data[token_key]
                args['url'] = random.choice(storage_urls)

            # Check for connection pool initialization (protected by a
            # semaphore)
            if args['url'] not in self.conn_pools:
                self._create_connection_pool(
                    args['url'],
                    call_info.get('connect_timeout',
                                  client.DEFAULT_CONNECT_TIMEOUT),
                    call_info.get('network_timeout',
                                  client.DEFAULT_NETWORK_TIMEOUT))

            try:
                fn_results = None
                with self.connection(args['url']) as conn:
                    fn_results = fn(http_conn=conn, **args)
                if fn_results:
                    if tries != 0:
                        logging.info('%r succeeded after %d tries', call_info,
                                     tries)
                    break
                tries += 1
                if tries > self.max_retries:
                    e = Exception('No fn_results for %r after %d retires' %
                                  (fn, self.max_retries))
                    e.retries = tries - 1
                    raise e
            # XXX The name of this method does not suggest that it
            # will also retry on socket-level errors. Regardless,
            # sometimes Swift refuses connections (probably when it's
            # way overloaded and the listen socket's connection queue
            # (in the kernel) is full, so the kernel just says RST).
            #
            # UPDATE: connections should be handled by the ConnectionPool
            # (which will trap socket.error and retry after a slight delay), so
            # socket.error should NOT get raised here for connection failures.
            # So hopefully this socket.error trapping code path will not get
            # hit.
            except socket.error as error:
                tries += 1
                if tries > self.max_retries:
                    error.retries = tries - 1
                    raise error
            except client.ClientException as error:
                tries += 1
                if error.http_status in statuses and \
                        tries <= self.max_retries:
                    if error.http_status == 401 and token_key:
                        if token_key in self.token_data and \
                                self.token_data[token_key][1] == args['token']:
                            self.token_data_lock.acquire()
                            try:
                                if token_key in self.token_data and \
                                        self.token_data[token_key][1] == \
                                        args['token']:
                                    logging.debug(
                                        'Deleting token %s',
                                        self.token_data[token_key][1])
                                    del self.token_data[token_key]
                            finally:
                                self.token_data_lock.release()
                    logging.debug("Retrying an error: %r", error)
                else:
                    error.retries = tries - 1
                    raise error
        fn_results['retries'] = tries
        return fn_results
Exemple #5
0
    def ignoring_http_responses(self, statuses, fn, call_info, **extra_keys):
        if 401 not in statuses:
            statuses += (401,)
        args = dict(
            container=call_info['container'],
            name=call_info['name'],
        )
        args.update(extra_keys)

        if 'auth_kwargs' not in call_info:
            raise ValueError('Got benchmark job without "auth_kwargs" key!')

        tries = 0
        while True:
            # Make sure we've got a current storage_url/token
            if call_info['auth_kwargs'].get('token', None):
                args['url'] = random.choice(
                    call_info['auth_kwargs']['storage_urls'])
                args['token'] = call_info['auth_kwargs']['token']
            else:
                token_key = self._token_key(call_info['auth_kwargs'])
                if token_key not in self.token_data:
                    self.token_data_lock.acquire()
                    collided = False
                    try:
                        if token_key not in self.token_data:
                            logging.debug('Authenticating with %r',
                                          call_info['auth_kwargs'])
                            storage_url, token = client.get_auth(
                                **call_info['auth_kwargs'])
                            override_urls = call_info['auth_kwargs'].get(
                                'storage_urls', None)
                            if override_urls:
                                logging.debug(
                                    'Will override auth storage url %s with '
                                    'one of %r', storage_url, override_urls)
                                storage_urls = override_urls
                            else:
                                storage_urls = [storage_url]
                            self.token_data[token_key] = (storage_urls, token)
                        else:
                            collided = True
                    finally:
                        self.token_data_lock.release()
                    if collided:
                        # Wait just a little bit if we just collided with
                        # another greenthread's re-auth
                        logging.debug('Collided on re-auth; sleeping 0.005')
                        gevent.sleep(0.005)
                storage_urls, args['token'] = self.token_data[token_key]
                args['url'] = random.choice(storage_urls)

            # Check for connection pool initialization (protected by a
            # semaphore)
            if args['url'] not in self.conn_pools:
                self._create_connection_pool(
                    args['url'],
                    call_info.get('connect_timeout',
                                  client.DEFAULT_CONNECT_TIMEOUT),
                    call_info.get('network_timeout',
                                  client.DEFAULT_NETWORK_TIMEOUT))

            try:
                fn_results = None
                with self.connection(args['url']) as conn:
                    fn_results = fn(http_conn=conn, **args)
                if fn_results:
                    if tries != 0:
                        logging.info('%r succeeded after %d tries',
                                     call_info, tries)
                    break
                tries += 1
                if tries > self.max_retries:
                    e = Exception('No fn_results for %r after %d retires' % (
                        fn, self.max_retries))
                    e.retries = tries - 1
                    raise e
            # XXX The name of this method does not suggest that it
            # will also retry on socket-level errors. Regardless,
            # sometimes Swift refuses connections (probably when it's
            # way overloaded and the listen socket's connection queue
            # (in the kernel) is full, so the kernel just says RST).
            #
            # UPDATE: connections should be handled by the ConnectionPool
            # (which will trap socket.error and retry after a slight delay), so
            # socket.error should NOT get raised here for connection failures.
            # So hopefully this socket.error trapping code path will not get
            # hit.
            except socket.error as error:
                tries += 1
                if tries > self.max_retries:
                    error.retries = tries - 1
                    raise error
            except client.ClientException as error:
                tries += 1
                if error.http_status in statuses and \
                        tries <= self.max_retries:
                    if error.http_status == 401 and token_key:
                        if token_key in self.token_data and \
                                self.token_data[token_key][1] == args['token']:
                            self.token_data_lock.acquire()
                            try:
                                if token_key in self.token_data and \
                                        self.token_data[token_key][1] == \
                                        args['token']:
                                    logging.debug(
                                        'Deleting token %s',
                                        self.token_data[token_key][1])
                                    del self.token_data[token_key]
                            finally:
                                self.token_data_lock.release()
                    logging.debug("Retrying an error: %r", error)
                else:
                    error.retries = tries - 1
                    raise error
        fn_results['retries'] = tries
        return fn_results
Exemple #6
0
    def run_scenario(self, auth_url, user, key, storage_url, token, scenario):
        """
        Runs a CRUD scenario, given cluster parameters and a Scenario object.

        :auth_url: Authentication URL for the Swift cluster
        :user: Account/Username to use (format is <account>:<username>)
        :key: Password for the Account/Username
        :scenario: Scenario object describing the benchmark run
        :returns: Collected result records from workers
        """

        run_state = RunState()

        self.drain_stats_queue()
        if not storage_url or not token:
            logging.debug("Authenticating to %s with %s/%s", auth_url, user, key)
            storage_url, token = client.get_auth(auth_url, user, key)
        else:
            logging.debug("Using token %s at %s", token, storage_url)

        logging.info(u'Starting scenario run for "%s"', scenario.name)

        # Ensure containers exist
        logging.info(
            "Ensuring %d containers (%s_*) exist; concurrency=%d...",
            len(scenario.containers),
            scenario.container_base,
            scenario.container_concurrency,
        )
        pool = eventlet.GreenPool(scenario.container_concurrency)
        for container in scenario.containers:
            pool.spawn_n(_container_creator, storage_url, token, container)
        pool.waitall()

        self.queue.use(ssbench.WORK_TUBE)

        # Enqueue initialization jobs
        logging.info("Initializing cluster with stock data (up to %d " "concurrent workers)", scenario.user_count)

        self.do_a_run(
            scenario.user_count,
            scenario.initial_jobs(),
            run_state.handle_initialization_result,
            ssbench.PRIORITY_SETUP,
            storage_url,
            token,
        )

        logging.info("Starting benchmark run (up to %d concurrent " "workers)", scenario.user_count)
        self.do_a_run(
            scenario.user_count,
            scenario.bench_jobs(),
            run_state.handle_run_result,
            ssbench.PRIORITY_WORK,
            storage_url,
            token,
            mapper_fn=run_state.fill_in_job,
            label="Benchmark Run:",
        )

        logging.info("Deleting population objects from cluster")
        self.do_a_run(
            scenario.user_count,
            run_state.cleanup_object_infos(),
            lambda *_: None,
            ssbench.PRIORITY_CLEANUP,
            storage_url,
            token,
            mapper_fn=_gen_cleanup_job,
        )

        return run_state.run_results