def add_multipart(self, image_file, image_size, bucket_obj, obj_name, loc,
                      verifier):

        checksum = hashlib.md5()
        pool_size = self.s3_store_thread_pools
        pool = eventlet.greenpool.GreenPool(size=pool_size)
        mpu = bucket_obj.initiate_multipart_upload(obj_name)
        LOG.debug("Multipart initiate key=%(obj_name)s, "
                  "UploadId=%(UploadId)s" %
                  {'obj_name': obj_name,
                   'UploadId': mpu.id})
        cstart = 0
        plist = []

        chunk_size = int(math.ceil(float(image_size) / MAX_PART_NUM))
        write_chunk_size = max(self.s3_store_large_object_chunk_size,
                               chunk_size)
        it = utils.chunkreadable(image_file, self.WRITE_CHUNKSIZE)
        buffered_chunk = b''
        while True:
            try:
                buffered_clen = len(buffered_chunk)
                if buffered_clen < write_chunk_size:
                    # keep reading data
                    read_chunk = next(it)
                    buffered_chunk += read_chunk
                    continue
                else:
                    write_chunk = buffered_chunk[:write_chunk_size]
                    remained_data = buffered_chunk[write_chunk_size:]
                    checksum.update(write_chunk)
                    if verifier:
                        verifier.update(write_chunk)
                    fp = six.BytesIO(write_chunk)
                    fp.seek(0)
                    part = UploadPart(mpu, fp, cstart + 1, len(write_chunk))
                    pool.spawn_n(run_upload, part)
                    plist.append(part)
                    cstart += 1
                    buffered_chunk = remained_data
            except StopIteration:
                if len(buffered_chunk) > 0:
                    # Write the last chunk data
                    write_chunk = buffered_chunk
                    checksum.update(write_chunk)
                    if verifier:
                        verifier.update(write_chunk)
                    fp = six.BytesIO(write_chunk)
                    fp.seek(0)
                    part = UploadPart(mpu, fp, cstart + 1, len(write_chunk))
                    pool.spawn_n(run_upload, part)
                    plist.append(part)
                break

        pedict = {}
        total_size = 0
        pool.waitall()

        for part in plist:
            pedict.update(part.etag)
            total_size += part.size

        success = True
        for part in plist:
            if not part.success:
                success = False

        if success:
            # Complete
            xml = get_mpu_xml(pedict)
            bucket_obj.complete_multipart_upload(obj_name,
                                                 mpu.id,
                                                 xml)
            checksum_hex = checksum.hexdigest()
            LOG.info(_LI("Multipart complete key=%(obj_name)s "
                         "UploadId=%(UploadId)s "
                         "Wrote %(total_size)d bytes to S3 key"
                         "named %(obj_name)s "
                         "with checksum %(checksum_hex)s") %
                     {'obj_name': obj_name,
                      'UploadId': mpu.id,
                      'total_size': total_size,
                      'checksum_hex': checksum_hex})
            return (loc.get_uri(), total_size, checksum_hex, {})
        else:
            # Abort
            bucket_obj.cancel_multipart_upload(obj_name, mpu.id)
            LOG.error(_LE("Some parts failed to upload to S3. "
                          "Aborted the object key=%(obj_name)s") %
                      {'obj_name': obj_name})
            msg = (_("Failed to add image object to S3. "
                     "key=%(obj_name)s") % {'obj_name': obj_name})
            raise glance_store.BackendException(msg)
Stores an image file with a multi part upload to S3 backend
dataset/ETHPy150Open openstack/glance_store/glance_store/_drivers/s3.py/Store.add_multipart