示例#1
0
def drop_privileges(user):
    """
    Change the effective user of the current process, resets the current
    directory to /.
    """
    if os.geteuid() == 0:
        groups = [g.gr_gid for g in grp.getgrall() if user in g.gr_mem]
        os.setgroups(groups)
    current_user = getuser()
    if user != current_user:
        try:
            user_entry = pwd.getpwnam(user)
        except KeyError as exc:
            raise OioException("User %s does not exist (%s). Are you running "
                               "your namespace with another user name?" %
                               (user, exc))
        try:
            os.setgid(user_entry[3])
            os.setuid(user_entry[2])
        except OSError as exc:
            raise OioException("Failed to switch uid to %s or gid to %s: %s" %
                               (user_entry[2], user_entry[3], exc))
        os.environ['HOME'] = user_entry[5]
        try:
            os.setsid()
        except OSError:
            pass
    os.chdir('/')
    os.umask(0o22)
示例#2
0
 def _load_handler(self, chunk_method):
     storage_method = STORAGE_METHODS.load(chunk_method)
     handler = self.handlers.get(storage_method.type)
     if not handler:
         raise OioException("No handler found for chunk method [%s]" %
                            chunk_method)
     return handler, storage_method
示例#3
0
 def _direct_request(self,
                     method,
                     url,
                     headers=None,
                     request_attempts=None,
                     **kwargs):
     if not request_attempts:
         request_attempts = self._request_attempts
     if request_attempts <= 0:
         raise OioException("Negative request attempts: %d" %
                            request_attempts)
     if kwargs.get("autocreate"):
         if not headers:
             headers = dict()
         headers["X-oio-action-mode"] = "autocreate"
         kwargs = kwargs.copy()
         kwargs.pop("autocreate")
     for i in range(request_attempts):
         try:
             return super(ProxyClient,
                          self)._direct_request(method,
                                                url,
                                                headers=headers,
                                                **kwargs)
         except ServiceBusy:
             if i >= request_attempts - 1:
                 raise
             # retry with exponential backoff
             ProxyClient._exp_sleep(i + 1)
示例#4
0
 def local_services(self):
     resp, body = self._request('GET', '/list')
     if resp.status_code == 200:
         return body
     else:
         raise OioException("failed to get list of local services: %s" %
                            resp.text)
示例#5
0
    def all_services(self, type_, full=False, **kwargs):
        """
        Get the list of all services of a specific type.

        :param type_: the type of services to get (ex: 'rawx')
        :type type_: `str`
        :param full: whether to get all metrics for each service
        :returns: the list of all services of the specified type.
        :rtype: `list` of `dict` objects, each containing at least
            - 'addr' (`str`),
            - 'id' (`str`),
            - 'score' (`int`),
            - 'tags' (`dict`).
        """
        params = {'type': type_}
        if full:
            params['full'] = '1'
        resp, body = self._request('GET', '/list', params=params, **kwargs)
        if resp.status == 200:
            # TODO(FVE): do that in the proxy
            for srv in body:
                if 'id' not in srv:
                    srv_id = srv['tags'].get('tag.service_id', srv['addr'])
                    srv['id'] = srv_id
            return body
        else:
            raise OioException("failed to get list of %s services: %s" %
                               (type_, resp.text))
示例#6
0
 def local_services(self):
     url = self.endpoint.replace('conscience', 'local/list')
     resp, body = self._direct_request('GET', url)
     if resp.status == 200:
         return body
     else:
         raise OioException("failed to get list of local services: %s" %
                            resp.text)
示例#7
0
 def next_instance(self, pool):
     uri = self._make_uri('lb/choose')
     params = {'pool': pool}
     resp, body = self._request('GET', uri, params=params)
     if resp.status_code == 200:
         return body[0]
     else:
         raise OioException('ERROR while getting next instance %s' % pool)
示例#8
0
 def service_types(self):
     params = {'what': 'types'}
     resp, body = self._request('GET', '/info', params=params)
     if resp.status == 200:
         return body
     else:
         raise OioException("ERROR while getting services types: %s" %
                            resp.text)
示例#9
0
 def resolve(self, srv_type, service_id):
     resp, body = self._request('GET', '/resolve',
                                params={'type': srv_type,
                                        'service_id': service_id})
     if resp.status == 200:
         return body
     else:
         raise OioException("failed to resolve servie id %s: %s" %
                            (service_id, resp.text))
示例#10
0
文件: client.py 项目: bhyvex/oio-sds
 def all_services(self, type_):
     uri = self._make_uri("conscience/list")
     params = {'type': type_}
     resp, body = self._request('GET', uri, params=params)
     if resp.status_code == 200:
         return body
     else:
         # FIXME: add resp error message
         raise OioException("ERROR while getting list of %s services" %
                            type_)
示例#11
0
 def _get_streams(self):
     for pos in range(len(self.meta_chunks)):
         handler = BackblazeChunkDownloadHandler(self.sysmeta,
                                                 self.meta_chunks[pos],
                                                 0, 0, None,
                                                 self.backblaze_infos)
         stream = handler.get_stream()
         if not stream:
             raise OioException("Error while downloading")
         yield stream
示例#12
0
 def all_services(self, type_, full=False, **kwargs):
     params = {'type': type_}
     if full:
         params['full'] = '1'
     resp, body = self._request('GET', '/list', params=params, **kwargs)
     if resp.status == 200:
         return body
     else:
         raise OioException("failed to get list of %s services: %s" %
                            (type_, resp.text))
示例#13
0
    def assign_services(self, service_type, max_per_rdir=None, **kwargs):
        all_services = self.cs.all_services(service_type, **kwargs)
        all_rdir = self.cs.all_services('rdir', True, **kwargs)
        if len(all_rdir) <= 0:
            raise ServiceUnavailable("No rdir service found in %s" % self.ns)

        by_id = {_make_id(self.ns, 'rdir', x['addr']): x for x in all_rdir}

        errors = list()
        for provider in all_services:
            provider_id = provider['tags'].get('tag.service_id',
                                               provider['addr'])

            try:
                resp = self.directory.list(RDIR_ACCT,
                                           provider_id,
                                           service_type='rdir',
                                           **kwargs)
                rdir_host = _filter_rdir_host(resp)
                try:
                    provider['rdir'] = by_id[_make_id(self.ns, 'rdir',
                                                      rdir_host)]
                except KeyError:
                    self.logger.warn("rdir %s linked to %s %s seems down",
                                     rdir_host, service_type, provider_id)
            except NotFound:
                try:
                    rdir = self._smart_link_rdir(provider_id,
                                                 all_rdir,
                                                 service_type=service_type,
                                                 max_per_rdir=max_per_rdir,
                                                 **kwargs)
                except OioException as exc:
                    self.logger.warn("Failed to link an rdir to %s %s: %s",
                                     service_type, provider_id, exc)
                    errors.append((provider_id, exc))
                    continue
                n_bases = by_id[rdir]['tags'].get("stat.opened_db_count", 0)
                by_id[rdir]['tags']["stat.opened_db_count"] = n_bases + 1
                provider['rdir'] = by_id[rdir]
            except OioException as exc:
                self.logger.warn(
                    "Failed to check rdir linked to %s %s "
                    "(thus won't try to make the link): %s", service_type,
                    provider_id, exc)
                errors.append((provider_id, exc))
        if errors:
            # group_chunk_errors is flexible enough to accept service addresses
            errors = group_chunk_errors(errors)
            if len(errors) == 1:
                err, addrs = errors.popitem()
                oio_reraise(type(err), err, str(addrs))
            else:
                raise OioException('Several errors encountered: %s' % errors)
        return all_services
示例#14
0
 def _delete(self, conn):
     sysmeta = conn['sysmeta']
     try_number = TRY_REQUEST_NUMBER
     try:
         conn['backblaze'].delete(self.backblaze_info['bucket_name'],
                                  sysmeta)
     except BackblazeException as b2e:
         if try_number == 0:
             raise OioException('backblaze delete error: %s'
                                % str(b2e))
         try_number -= 1
示例#15
0
 def _delete(self, conn):
     sysmeta = conn['sysmeta']
     try_number = TRY_REQUEST_NUMBER
     while True:
         try:
             conn['backblaze'].delete(self.backblaze_info['bucket_name'],
                                      sysmeta)
             break
         except BackblazeException as b2e:
             if try_number == 0:
                 raise OioException('backblaze delete error: %s' % str(b2e))
             else:
                 eventlet.sleep(pow(2, TRY_REQUEST_NUMBER - try_number))
         try_number -= 1
示例#16
0
    def next_instances(self, pool, size=None, **kwargs):
        """
        Get the next service instances from the specified pool.

        :keyword size: number of services to get
        :type size: `int`
        """
        params = {'type': pool}
        if size is not None:
            params['size'] = size
        resp, body = self._request('GET', '/choose', params=params, **kwargs)
        if resp.status == 200:
            return body
        else:
            raise OioException('ERROR while getting next instance %s' % pool)
示例#17
0
文件: client.py 项目: bhyvex/oio-sds
 def next_instances(self, pool, **kwargs):
     """
     Get the next service instances from the specified pool.
     Available options:
     - size:   number of services to get
     - slot:   comma-separated list of slots to poll
     """
     uri = self._make_uri('lb/choose')
     params = {'type': pool}
     params.update(kwargs)
     resp, body = self._request('GET', uri, params=params)
     if resp.status_code == 200:
         return body
     else:
         raise OioException('ERROR while getting next instance %s' % pool)
示例#18
0
    def next_instances(self, pool, **kwargs):
        """
        Get the next service instances from the specified pool.

        :keyword size: number of services to get
        :type size: `int`
        :keyword slot: comma-separated list of slots to poll
        :type slot: `str`
        """
        params = {'type': pool}
        params.update(kwargs)
        resp, body = self._request('GET', '/choose', params=params)
        if resp.status == 200:
            return body
        else:
            raise OioException('ERROR while getting next instance %s' % pool)
示例#19
0
 def _make_stream(self, source):
     result = None
     data = None
     for chunk in self.chunks:
         self.meta['name'] = _get_name(chunk)
         try:
             try_number = TRY_REQUEST_NUMBER
             data = source.download(self.backblaze_info['bucket_name'],
                                    self.meta, self.headers)
         except BackblazeException as b2e:
             if try_number == 0:
                 raise OioException('backblaze download error: %s'
                                    % str(b2e))
             try_number -= 1
     if data:
         result = data
     return result
示例#20
0
    def poll(self, pool, **kwargs):
        """
        Get a set of services from a predefined pool.

        :keyword avoid: service IDs that must be avoided
        :type avoid: `list`
        :keyword known: service IDs that are already known
        :type known: `list`
        """
        params = {'pool': pool}
        ibody = dict()
        ibody.update(kwargs)
        resp, obody = self._request('POST', '/poll', params=params,
                                    data=json.dumps(ibody))
        if resp.status == 200:
            return obody
        else:
            raise OioException("Failed to poll %s: %s" % (pool, resp.text))
示例#21
0
 def next_instances(self, pool, **kwargs):
     """
     Get the next service instances from the specified pool.
     Available options:
     - size:   number of services to get
     - stgcls: storage class of the services
     - tagk:   name of the tag to be matched
     - tagv:   value of the tag to be matched (required if tagk specified)
     """
     uri = self._make_uri('lb/choose')
     params = {'type': pool}
     params.update(kwargs)
     resp, body = self._request('GET', uri, params=params)
     if resp.status_code == 200:
         return body
     else:
         raise OioException(
             'ERROR while getting next instance %s' % pool)
示例#22
0
    def _upload_chunks(self, conn, size, sha1, md5, temp):
        try_number = TRY_REQUEST_NUMBER
        while True:
            self.meta_chunk['size'] = size
            try:
                logger.debug("sha1: %s", sha1)
                conn['backblaze'].upload(self.backblaze_info['bucket_name'],
                                         self.sysmeta, temp, sha1)
                break
            except BackblazeException as b2e:
                temp.seek(0)
                if try_number == 0:
                    raise OioException('backblaze upload error: %s'
                                       % str(b2e))
                try_number -= 1

        self.meta_chunk['hash'] = md5
        return self.meta_chunk["size"], [self.meta_chunk]
示例#23
0
    def all_services(self, type_, full=False, **kwargs):
        """
        Get the list of all services of a specific type.

        :param type_: the type of services to get (ex: 'rawx')
        :type type_: `str`
        :param full: whether to get all metrics for each service
        :returns: the list of all services of the specified type
        :rtype: `list` of `dict`
        """
        params = {'type': type_}
        if full:
            params['full'] = '1'
        resp, body = self._request('GET', '/list', params=params, **kwargs)
        if resp.status == 200:
            return body
        else:
            raise OioException("failed to get list of %s services: %s"
                               % (type_, resp.text))
示例#24
0
    def _direct_request(self,
                        method,
                        url,
                        headers=None,
                        request_attempts=None,
                        **kwargs):
        if not request_attempts:
            request_attempts = self._request_attempts
        if request_attempts <= 0:
            raise OioException("Negative request attempts: %d" %
                               request_attempts)
        if kwargs.get("autocreate"):
            if not headers:
                headers = dict()
            headers[HEADER_PREFIX + "action-mode"] = "autocreate"
            kwargs.pop("autocreate")
        if kwargs.get("tls"):
            headers = headers or dict()
            headers[HEADER_PREFIX + "upgrade-to-tls"] = kwargs.pop("tls")

        for i in range(request_attempts):
            try:
                return super(ProxyClient,
                             self)._direct_request(method,
                                                   url,
                                                   headers=headers,
                                                   **kwargs)
            except ServiceBusy:
                if i >= request_attempts - 1:
                    raise
                # retry with exponential backoff
                ProxyClient._exp_sleep(i + 1)
            except Conflict:
                if i > 0 and method == 'POST':
                    # We were retrying a POST operation, it's highly probable
                    # that the original operation succeeded after we timed
                    # out. So we consider this a success and don't raise
                    # the exception.
                    return None, None
                raise
示例#25
0
    def _upload_chunks(self, conn, size, sha1, md5, temp):
        try_number = TRY_REQUEST_NUMBER
        while True:
            self.meta_chunk[0]['size'] = size
            try:
                conn['backblaze'].upload(self.backblaze_info['bucket_name'],
                                         self.sysmeta, temp, sha1)
                break
            except BackblazeException as b2e:
                temp.seek(0)
                if try_number == 0:
                    logger.debug('headers sent: %s' % str(b2e.headers_send))
                    raise OioException('backblaze upload error: %s' % str(b2e))
                else:
                    sleep_time_default = pow(2,
                                             TRY_REQUEST_NUMBER - try_number)
                    sleep = b2e.headers_received.get("Retry-After",
                                                     sleep_time_default)
                    eventlet.sleep(sleep)
                try_number -= 1

        self.meta_chunk[0]['hash'] = md5
        return self.meta_chunk[0]["size"], self.meta_chunk
示例#26
0
文件: tool.py 项目: vandanabn/oio-sds
    def __init__(self, conf, tool):
        super(_DistributedDispatcher, self).__init__(conf, tool)
        self.sending = False

        # All available beanstalkd
        conscience_client = ConscienceClient(self.conf)
        all_beanstalkd = conscience_client.all_services('beanstalkd')
        all_available_beanstalkd = dict()
        for beanstalkd in all_beanstalkd:
            if beanstalkd['score'] <= 0:
                continue
            all_available_beanstalkd[beanstalkd['addr']] = beanstalkd
        if not all_available_beanstalkd:
            raise OioException('No beanstalkd available')

        # Beanstalkd workers
        workers_tube = self.conf.get('distributed_beanstalkd_worker_tube') \
            or self.tool.DEFAULT_DISTRIBUTED_BEANSTALKD_WORKER_TUBE
        self.beanstalkd_workers = dict()
        for _, beanstalkd in all_available_beanstalkd.items():
            beanstalkd_worker_addr = beanstalkd['addr']

            # If the tube exists,
            # there should be a service that listens to this tube
            tubes = Beanstalk.from_url('beanstalk://' +
                                       beanstalkd_worker_addr).tubes()
            if workers_tube not in tubes:
                continue

            beanstalkd_worker = BeanstalkdSender(beanstalkd_worker_addr,
                                                 workers_tube, self.logger)
            self.beanstalkd_workers[beanstalkd_worker_addr] = beanstalkd_worker
            self.logger.info(
                'Beanstalkd %s using tube %s is selected as a worker',
                beanstalkd_worker.addr, beanstalkd_worker.tube)
        if not self.beanstalkd_workers:
            raise OioException('No beanstalkd worker available')

        # Beanstalkd reply
        beanstalkd_reply = dict()
        try:
            local_services = conscience_client.local_services()
            for local_service in local_services:
                if local_service['type'] != 'beanstalkd':
                    continue
                beanstalkd = all_available_beanstalkd.get(
                    local_service['addr'])
                if beanstalkd is None:
                    continue
                if beanstalkd_reply \
                        and beanstalkd_reply['score'] >= beanstalkd['score']:
                    continue
                beanstalkd_reply = beanstalkd
        except Exception as exc:  # pylint: disable=broad-except
            self.logger.warning(
                'ERROR when searching for beanstalkd locally: %s', exc)
        if not beanstalkd_reply:
            self.logger.warn('No beanstalkd available locally')

            try:
                beanstalkd = conscience_client.next_instance('beanstalkd')
                beanstalkd_reply = all_available_beanstalkd[beanstalkd['addr']]
            except Exception as exc:  # pylint: disable=broad-except
                self.logger.warning('ERROR when searching for beanstalkd: %s',
                                    exc)
        beanstalkd_reply_addr = beanstalkd_reply['addr']

        # If the tube exists, another service must have already used this tube
        tube_reply = workers_tube + '.reply.' + str(time.time())
        tubes = Beanstalk.from_url('beanstalk://' +
                                   beanstalkd_reply_addr).tubes()
        if tube_reply in tubes:
            raise OioException('Beanstalkd %s using tube %s is already used')

        self.beanstalkd_reply = BeanstalkdListener(beanstalkd_reply_addr,
                                                   tube_reply, self.logger)
        self.logger.info(
            'Beanstalkd %s using tube %s is selected for the replies',
            self.beanstalkd_reply.addr, self.beanstalkd_reply.tube)
示例#27
0
    def __init__(self, conf, tool):
        super(_DistributedDispatcher, self).__init__(conf, tool)
        self.sending = None

        self.max_items_per_second = int_value(
            self.conf.get('items_per_second'),
            self.tool.DEFAULT_ITEM_PER_SECOND)

        # All available beanstalkd
        conscience_client = ConscienceClient(self.conf)
        all_beanstalkd = conscience_client.all_services('beanstalkd')
        all_available_beanstalkd = dict()
        for beanstalkd in all_beanstalkd:
            if beanstalkd['score'] <= 0:
                continue
            all_available_beanstalkd[beanstalkd['addr']] = beanstalkd
        if not all_available_beanstalkd:
            raise OioException('No beanstalkd available')

        # Beanstalkd workers
        workers_tube = self.conf.get('distributed_beanstalkd_worker_tube') \
            or self.tool.DEFAULT_DISTRIBUTED_BEANSTALKD_WORKER_TUBE
        self.beanstalkd_workers = dict()
        for beanstalkd in locate_tube(all_available_beanstalkd.values(),
                                      workers_tube):
            beanstalkd_worker = BeanstalkdSender(beanstalkd['addr'],
                                                 workers_tube, self.logger)
            self.beanstalkd_workers[beanstalkd['addr']] = beanstalkd_worker
            self.logger.info(
                'Beanstalkd %s using tube %s is selected as a worker',
                beanstalkd_worker.addr, beanstalkd_worker.tube)
        if not self.beanstalkd_workers:
            raise OioException('No beanstalkd worker available')
        nb_workers = len(self.beanstalkd_workers)
        if self.max_items_per_second > 0:
            # Max 2 seconds in advance
            queue_size_per_worker = self.max_items_per_second * 2 / nb_workers
        else:
            queue_size_per_worker = 64
        for _, beanstalkd_worker in self.beanstalkd_workers.items():
            beanstalkd_worker.low_limit = queue_size_per_worker / 2
            beanstalkd_worker.high_limit = queue_size_per_worker

        # Beanstalkd reply
        beanstalkd_reply = dict()
        try:
            local_services = conscience_client.local_services()
            for local_service in local_services:
                if local_service['type'] != 'beanstalkd':
                    continue
                beanstalkd = all_available_beanstalkd.get(
                    local_service['addr'])
                if beanstalkd is None:
                    continue
                if beanstalkd_reply \
                        and beanstalkd_reply['score'] >= beanstalkd['score']:
                    continue
                beanstalkd_reply = beanstalkd
        except Exception as exc:  # pylint: disable=broad-except
            self.logger.warning(
                'ERROR when searching for beanstalkd locally: %s', exc)
        if not beanstalkd_reply:
            self.logger.warn('No beanstalkd available locally')

            try:
                beanstalkd = conscience_client.next_instance('beanstalkd')
                beanstalkd_reply = all_available_beanstalkd[beanstalkd['addr']]
            except Exception as exc:  # pylint: disable=broad-except
                self.logger.warning('ERROR when searching for beanstalkd: %s',
                                    exc)
        beanstalkd_reply_addr = beanstalkd_reply['addr']

        # If the tube exists, another service must have already used this tube
        tube_reply = workers_tube + '.reply.' + str(time.time())
        tubes = Beanstalk.from_url('beanstalk://' +
                                   beanstalkd_reply_addr).tubes()
        if tube_reply in tubes:
            raise OioException('Beanstalkd %s using tube %s is already used')

        self.beanstalkd_reply = BeanstalkdListener(beanstalkd_reply_addr,
                                                   tube_reply, self.logger)
        self.logger.info(
            'Beanstalkd %s using tube %s is selected for the replies',
            self.beanstalkd_reply.addr, self.beanstalkd_reply.tube)
示例#28
0
文件: client.py 项目: lhllacp/oio-sds
    def assign_services(self,
                        service_type,
                        max_per_rdir=None,
                        min_dist=None,
                        service_id=None,
                        reassign=False,
                        **kwargs):
        """
        Assign an rdir service to all `service_type` servers that aren't
        already assigned one.

        :param max_per_rdir: Maximum number of services an rdir can handle.
        :type max_per_rdir: `int`
        :param min_dist: Minimum required distance between any service and
            its assigned rdir service.
        :type min_dist: `int`
        :param service_id: Assign only this service ID.
        :type service_id: `str`
        :param reassign: Reassign an rdir service.
        :type reassign: `bool`
        :param dry_run: Display actions but do nothing.
        :type dry_run: `bool`
        :returns: The list of `service_type` services that were assigned
            rdir services.
        """
        all_services = self.cs.all_services(service_type, **kwargs)
        if service_id:
            for provider in all_services:
                provider_id = provider['tags'].get('tag.service_id',
                                                   provider['addr'])
                if service_id == provider_id:
                    break
            else:
                raise ValueError('%s isn\'t a %s' % (service_id, service_type))
            all_services = [provider]
        all_rdir = self.cs.all_services('rdir', True, **kwargs)
        if len(all_rdir) <= 0:
            raise ServiceUnavailable("No rdir service found in %s" % self.ns)

        by_id = _build_dict_by_id(self.ns, all_rdir)

        errors = list()
        for provider in all_services:
            provider_id = provider['tags'].get('tag.service_id',
                                               provider['addr'])

            try:
                resp = self.directory.list(RDIR_ACCT,
                                           provider_id,
                                           service_type='rdir',
                                           **kwargs)
                rdir_host = _filter_rdir_host(resp)
                try:
                    rdir = by_id[_make_id(self.ns, 'rdir', rdir_host)]
                    if reassign:
                        rdir['tags']['stat.opened_db_count'] = \
                            rdir['tags'].get('stat.opened_db_count', 0) - 1
                        # TODO(adu) Delete database
                        raise NotFound('Reassign an rdir services')
                    provider['rdir'] = rdir
                except KeyError:
                    self.logger.warn("rdir %s linked to %s %s seems down",
                                     rdir_host, service_type, provider_id)
                    if reassign:
                        raise NotFound('Reassign an rdir services')
            except NotFound:
                try:
                    rdir = self._smart_link_rdir(provider_id,
                                                 all_rdir,
                                                 service_type=service_type,
                                                 max_per_rdir=max_per_rdir,
                                                 min_dist=min_dist,
                                                 reassign=reassign,
                                                 **kwargs)
                except OioException as exc:
                    self.logger.warn("Failed to link an rdir to %s %s: %s",
                                     service_type, provider_id, exc)
                    errors.append((provider_id, exc))
                    continue
                n_bases = by_id[rdir]['tags'].get("stat.opened_db_count", 0)
                by_id[rdir]['tags']["stat.opened_db_count"] = n_bases + 1
                provider['rdir'] = by_id[rdir]
            except OioException as exc:
                self.logger.warn(
                    "Failed to check rdir linked to %s %s "
                    "(thus won't try to make the link): %s", service_type,
                    provider_id, exc)
                errors.append((provider_id, exc))
        if errors:
            # group_chunk_errors is flexible enough to accept service addresses
            errors = group_chunk_errors(errors)
            if len(errors) == 1:
                err, addrs = errors.popitem()
                oio_reraise(type(err), err, str(addrs))
            else:
                raise OioException('Several errors encountered: %s' % errors)
        return all_services
示例#29
0
    def _stream_big_chunks(self, source, conn, temp):
        max_chunk_size = conn['backblaze'].BACKBLAZE_MAX_CHUNK_SIZE
        sha1_array = []
        res = None
        size, sha1, md5 = _read_to_temp(max_chunk_size, source,
                                        self.checksum, temp)

        # obligated to read max_chunk_size + 1 bytes
        # if the size of the file is max_chunk_size
        # backblaze will not take it because
        # the upload part must have at least 2 parts
        first_byte = source.read(1)
        if not first_byte:
            return self._upload_chunks(conn, size, sha1, md5, temp)

        tries = TRY_REQUEST_NUMBER
        while True:
            try:
                res = conn['backblaze'].upload_part_begin(
                    self.backblaze_info['bucket_name'], self.sysmeta)
                break
            except BackblazeException as b2e:
                tries = tries - 1
                if tries == 0:
                    raise OioException('Error at the beginning of upload: %s'
                                       % str(b2e))
        file_id = res['fileId']
        part_num = 1
        bytes_read = size + 1
        tries = TRY_REQUEST_NUMBER
        while True:
            while True:
                if bytes_read + max_chunk_size > self.meta_chunk['size']:
                    to_read = self.meta_chunk['size'] - bytes_read
                else:
                    to_read = max_chunk_size
                try:
                    res, sha1 = conn['backblaze'].upload_part(file_id, temp,
                                                              part_num, sha1)
                    break
                except BackblazeException as b2e:
                    temp.seek(0)
                    tries = tries - 1
                    if tries == 0:
                        raise OioException('Error during upload: %s'
                                           % str(b2e))
            part_num += 1
            sha1_array.append(sha1)
            temp.seek(0)
            temp.truncate(0)
            size, sha1, md5 = _read_to_temp(to_read, source,
                                            self.checksum, temp,
                                            first_byte)
            first_byte = None
            bytes_read = bytes_read + size
            if size == 0:
                break
        tries = TRY_REQUEST_NUMBER
        while True:
            try:
                res = conn['backblaze'].upload_part_end(file_id,
                                                        sha1_array)
                break
            except BackblazeException as b2e:
                tries = tries - 1
                if tries == 0:
                    raise OioException('Error at the end of upload: %s'
                                       % str(b2e))

        self.meta_chunk['hash'] = md5
        return bytes_read, [self.meta_chunk]