2025-01-21 20:52:28 +08:00
|
|
|
#
|
|
|
|
|
# Copyright 2025 The InfiniFlow Authors. All Rights Reserved.
|
|
|
|
|
#
|
|
|
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
# you may not use this file except in compliance with the License.
|
|
|
|
|
# You may obtain a copy of the License at
|
|
|
|
|
#
|
|
|
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
#
|
|
|
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
# See the License for the specific language governing permissions and
|
|
|
|
|
# limitations under the License.
|
|
|
|
|
#
|
|
|
|
|
|
2024-11-14 17:13:48 +08:00
|
|
|
import logging
|
2024-09-09 09:41:14 +08:00
|
|
|
import os
|
|
|
|
|
import time
|
|
|
|
|
from io import BytesIO
|
2025-11-02 12:24:08 +08:00
|
|
|
from common.decorator import singleton
|
2024-09-09 09:41:14 +08:00
|
|
|
from azure.storage.blob import ContainerClient
|
2025-11-06 09:36:38 +08:00
|
|
|
from common import settings
|
2024-09-09 09:41:14 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
@singleton
|
2025-03-05 18:03:53 +08:00
|
|
|
class RAGFlowAzureSasBlob:
|
2024-09-09 09:41:14 +08:00
|
|
|
def __init__(self):
|
|
|
|
|
self.conn = None
|
2025-11-06 09:36:38 +08:00
|
|
|
self.container_url = os.getenv('CONTAINER_URL', settings.AZURE["container_url"])
|
|
|
|
|
self.sas_token = os.getenv('SAS_TOKEN', settings.AZURE["sas_token"])
|
2024-09-09 09:41:14 +08:00
|
|
|
self.__open__()
|
|
|
|
|
|
|
|
|
|
def __open__(self):
|
|
|
|
|
try:
|
|
|
|
|
if self.conn:
|
|
|
|
|
self.__close__()
|
2024-11-12 17:35:13 +08:00
|
|
|
except Exception:
|
2024-09-09 09:41:14 +08:00
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
try:
|
2024-10-08 18:26:30 +08:00
|
|
|
self.conn = ContainerClient.from_container_url(self.container_url + "?" + self.sas_token)
|
2024-11-12 17:35:13 +08:00
|
|
|
except Exception:
|
2024-11-14 17:13:48 +08:00
|
|
|
logging.exception("Fail to connect %s " % self.container_url)
|
2024-09-09 09:41:14 +08:00
|
|
|
|
|
|
|
|
def __close__(self):
|
|
|
|
|
del self.conn
|
|
|
|
|
self.conn = None
|
|
|
|
|
|
|
|
|
|
def health(self):
|
2024-12-08 14:21:12 +08:00
|
|
|
_bucket, fnm, binary = "txtxtxtxt1", "txtxtxtxt1", b"_t@@@1"
|
2026-05-08 12:06:28 +08:00
|
|
|
return self.conn.upload_blob(name=f"{_bucket}/{fnm}", data=BytesIO(binary), length=len(binary))
|
2024-09-09 09:41:14 +08:00
|
|
|
|
2026-04-23 20:40:54 +08:00
|
|
|
def put(self, bucket, fnm, binary, tenant_id=None):
|
fix: prepend bucket prefix to Azure SPN and SAS storage paths (#14185)
## Summary
Fixes #14159 — files from different datasets can overwrite each other in
Azure Blob storage.
## Problem
Both `azure_spn_conn.py` and `azure_sas_conn.py` ignore the `bucket`
parameter in all storage operations (`put`, `get`, `rm`, `obj_exist`,
`get_presigned_url`). Files are stored flat using only the filename, so
two datasets containing a file with the same name will overwrite each
other.
The MinIO and S3 implementations correctly use the bucket (typically the
knowledge base ID) as a path prefix to create logical folder isolation:
- MinIO: uses `use_prefix_path` decorator → `{orig_bucket}/{fnm}`
- S3: uses `use_prefix_path` decorator → `{prefix_path}/{bucket}/{fnm}`
## Fix
Prepend `{bucket}/` to the file path in all 5 operations across both
Azure connector files:
| File | Methods fixed |
|------|---------------|
| `azure_spn_conn.py` | `put`, `get`, `rm`, `obj_exist`,
`get_presigned_url` |
| `azure_sas_conn.py` | `put`, `get`, `rm`, `obj_exist`,
`get_presigned_url` |
This matches the existing convention where `bucket` is the knowledge
base ID used as a directory prefix.
## ⚠️ Migration Note
Existing Azure SPN/SAS deployments have files stored without the bucket
prefix. After this fix, new files will be stored under
`{bucket}/{filename}` while existing files remain at `{filename}`. A
one-time migration script or manual file move may be needed for existing
deployments. New deployments are unaffected.
## Testing
- Verified the fix is consistent across all 5 methods in both files
- The `health()` method is intentionally left unchanged as it uses a
hardcoded test filename without bucket semantics
Co-authored-by: Jin Hai <haijin.chn@gmail.com>
2026-05-07 20:48:32 +08:00
|
|
|
blob_name = f"{bucket}/{fnm}"
|
2024-09-09 09:41:14 +08:00
|
|
|
for _ in range(3):
|
|
|
|
|
try:
|
fix: prepend bucket prefix to Azure SPN and SAS storage paths (#14185)
## Summary
Fixes #14159 — files from different datasets can overwrite each other in
Azure Blob storage.
## Problem
Both `azure_spn_conn.py` and `azure_sas_conn.py` ignore the `bucket`
parameter in all storage operations (`put`, `get`, `rm`, `obj_exist`,
`get_presigned_url`). Files are stored flat using only the filename, so
two datasets containing a file with the same name will overwrite each
other.
The MinIO and S3 implementations correctly use the bucket (typically the
knowledge base ID) as a path prefix to create logical folder isolation:
- MinIO: uses `use_prefix_path` decorator → `{orig_bucket}/{fnm}`
- S3: uses `use_prefix_path` decorator → `{prefix_path}/{bucket}/{fnm}`
## Fix
Prepend `{bucket}/` to the file path in all 5 operations across both
Azure connector files:
| File | Methods fixed |
|------|---------------|
| `azure_spn_conn.py` | `put`, `get`, `rm`, `obj_exist`,
`get_presigned_url` |
| `azure_sas_conn.py` | `put`, `get`, `rm`, `obj_exist`,
`get_presigned_url` |
This matches the existing convention where `bucket` is the knowledge
base ID used as a directory prefix.
## ⚠️ Migration Note
Existing Azure SPN/SAS deployments have files stored without the bucket
prefix. After this fix, new files will be stored under
`{bucket}/{filename}` while existing files remain at `{filename}`. A
one-time migration script or manual file move may be needed for existing
deployments. New deployments are unaffected.
## Testing
- Verified the fix is consistent across all 5 methods in both files
- The `health()` method is intentionally left unchanged as it uses a
hardcoded test filename without bucket semantics
Co-authored-by: Jin Hai <haijin.chn@gmail.com>
2026-05-07 20:48:32 +08:00
|
|
|
return self.conn.upload_blob(name=blob_name, data=BytesIO(binary), length=len(binary))
|
2024-11-12 17:35:13 +08:00
|
|
|
except Exception:
|
fix: prepend bucket prefix to Azure SPN and SAS storage paths (#14185)
## Summary
Fixes #14159 — files from different datasets can overwrite each other in
Azure Blob storage.
## Problem
Both `azure_spn_conn.py` and `azure_sas_conn.py` ignore the `bucket`
parameter in all storage operations (`put`, `get`, `rm`, `obj_exist`,
`get_presigned_url`). Files are stored flat using only the filename, so
two datasets containing a file with the same name will overwrite each
other.
The MinIO and S3 implementations correctly use the bucket (typically the
knowledge base ID) as a path prefix to create logical folder isolation:
- MinIO: uses `use_prefix_path` decorator → `{orig_bucket}/{fnm}`
- S3: uses `use_prefix_path` decorator → `{prefix_path}/{bucket}/{fnm}`
## Fix
Prepend `{bucket}/` to the file path in all 5 operations across both
Azure connector files:
| File | Methods fixed |
|------|---------------|
| `azure_spn_conn.py` | `put`, `get`, `rm`, `obj_exist`,
`get_presigned_url` |
| `azure_sas_conn.py` | `put`, `get`, `rm`, `obj_exist`,
`get_presigned_url` |
This matches the existing convention where `bucket` is the knowledge
base ID used as a directory prefix.
## ⚠️ Migration Note
Existing Azure SPN/SAS deployments have files stored without the bucket
prefix. After this fix, new files will be stored under
`{bucket}/{filename}` while existing files remain at `{filename}`. A
one-time migration script or manual file move may be needed for existing
deployments. New deployments are unaffected.
## Testing
- Verified the fix is consistent across all 5 methods in both files
- The `health()` method is intentionally left unchanged as it uses a
hardcoded test filename without bucket semantics
Co-authored-by: Jin Hai <haijin.chn@gmail.com>
2026-05-07 20:48:32 +08:00
|
|
|
logging.exception(f"Fail put {blob_name}")
|
2024-09-09 09:41:14 +08:00
|
|
|
self.__open__()
|
|
|
|
|
time.sleep(1)
|
|
|
|
|
|
|
|
|
|
def rm(self, bucket, fnm):
|
|
|
|
|
try:
|
fix: prepend bucket prefix in Azure Blob (SAS/SPN) to prevent cross-dataset file overwrites (#14174)
Fixes #14159
## Problem
The `put()`, `get()`, `rm()`, and `obj_exist()` methods in both
`azure_spn_conn.py` and `azure_sas_conn.py` ignore the `bucket`
parameter entirely, storing all files flat using only the filename. This
causes files from different datasets to overwrite each other when they
share the same filename.
By contrast, the MinIO and S3 implementations correctly use the bucket
(typically the knowledge base ID) as a path prefix, creating logical
folder isolation like `{kb_id}/{filename}`.
## Solution
Prepend the `bucket` parameter as a path prefix to all file operations
in both Azure storage implementations:
- `azure_spn_conn.py`: `create_file`, `delete_file`, `get_file_client`
now use `f"{bucket}/{fnm}"`
- `azure_sas_conn.py`: `upload_blob`, `delete_blob`, `download_blob`,
`get_blob_client` now use `f"{bucket}/{fnm}"`
This matches the behavior of all other storage backends (MinIO, S3) and
prevents filename collisions across knowledge bases.
## Testing
- Verified the fix aligns with how MinIO/S3 connectors handle the bucket
parameter
- The `health()` method is left unchanged as it uses a fixed test path
for connectivity checks only
Co-authored-by: octo-patch <octo-patch@github.com>
Co-authored-by: Jin Hai <haijin.chn@gmail.com>
2026-05-07 17:13:43 +08:00
|
|
|
self.conn.delete_blob(f"{bucket}/{fnm}")
|
2024-11-12 17:35:13 +08:00
|
|
|
except Exception:
|
2024-11-14 17:13:48 +08:00
|
|
|
logging.exception(f"Fail rm {bucket}/{fnm}")
|
2024-09-09 09:41:14 +08:00
|
|
|
|
|
|
|
|
def get(self, bucket, fnm):
|
fix: prepend bucket prefix to Azure SPN and SAS storage paths (#14185)
## Summary
Fixes #14159 — files from different datasets can overwrite each other in
Azure Blob storage.
## Problem
Both `azure_spn_conn.py` and `azure_sas_conn.py` ignore the `bucket`
parameter in all storage operations (`put`, `get`, `rm`, `obj_exist`,
`get_presigned_url`). Files are stored flat using only the filename, so
two datasets containing a file with the same name will overwrite each
other.
The MinIO and S3 implementations correctly use the bucket (typically the
knowledge base ID) as a path prefix to create logical folder isolation:
- MinIO: uses `use_prefix_path` decorator → `{orig_bucket}/{fnm}`
- S3: uses `use_prefix_path` decorator → `{prefix_path}/{bucket}/{fnm}`
## Fix
Prepend `{bucket}/` to the file path in all 5 operations across both
Azure connector files:
| File | Methods fixed |
|------|---------------|
| `azure_spn_conn.py` | `put`, `get`, `rm`, `obj_exist`,
`get_presigned_url` |
| `azure_sas_conn.py` | `put`, `get`, `rm`, `obj_exist`,
`get_presigned_url` |
This matches the existing convention where `bucket` is the knowledge
base ID used as a directory prefix.
## ⚠️ Migration Note
Existing Azure SPN/SAS deployments have files stored without the bucket
prefix. After this fix, new files will be stored under
`{bucket}/{filename}` while existing files remain at `{filename}`. A
one-time migration script or manual file move may be needed for existing
deployments. New deployments are unaffected.
## Testing
- Verified the fix is consistent across all 5 methods in both files
- The `health()` method is intentionally left unchanged as it uses a
hardcoded test filename without bucket semantics
Co-authored-by: Jin Hai <haijin.chn@gmail.com>
2026-05-07 20:48:32 +08:00
|
|
|
blob_name = f"{bucket}/{fnm}"
|
2024-09-09 09:41:14 +08:00
|
|
|
for _ in range(1):
|
|
|
|
|
try:
|
fix: prepend bucket prefix to Azure SPN and SAS storage paths (#14185)
## Summary
Fixes #14159 — files from different datasets can overwrite each other in
Azure Blob storage.
## Problem
Both `azure_spn_conn.py` and `azure_sas_conn.py` ignore the `bucket`
parameter in all storage operations (`put`, `get`, `rm`, `obj_exist`,
`get_presigned_url`). Files are stored flat using only the filename, so
two datasets containing a file with the same name will overwrite each
other.
The MinIO and S3 implementations correctly use the bucket (typically the
knowledge base ID) as a path prefix to create logical folder isolation:
- MinIO: uses `use_prefix_path` decorator → `{orig_bucket}/{fnm}`
- S3: uses `use_prefix_path` decorator → `{prefix_path}/{bucket}/{fnm}`
## Fix
Prepend `{bucket}/` to the file path in all 5 operations across both
Azure connector files:
| File | Methods fixed |
|------|---------------|
| `azure_spn_conn.py` | `put`, `get`, `rm`, `obj_exist`,
`get_presigned_url` |
| `azure_sas_conn.py` | `put`, `get`, `rm`, `obj_exist`,
`get_presigned_url` |
This matches the existing convention where `bucket` is the knowledge
base ID used as a directory prefix.
## ⚠️ Migration Note
Existing Azure SPN/SAS deployments have files stored without the bucket
prefix. After this fix, new files will be stored under
`{bucket}/{filename}` while existing files remain at `{filename}`. A
one-time migration script or manual file move may be needed for existing
deployments. New deployments are unaffected.
## Testing
- Verified the fix is consistent across all 5 methods in both files
- The `health()` method is intentionally left unchanged as it uses a
hardcoded test filename without bucket semantics
Co-authored-by: Jin Hai <haijin.chn@gmail.com>
2026-05-07 20:48:32 +08:00
|
|
|
r = self.conn.download_blob(blob_name)
|
2024-09-09 09:41:14 +08:00
|
|
|
return r.read()
|
2024-11-12 17:35:13 +08:00
|
|
|
except Exception:
|
fix: prepend bucket prefix to Azure SPN and SAS storage paths (#14185)
## Summary
Fixes #14159 — files from different datasets can overwrite each other in
Azure Blob storage.
## Problem
Both `azure_spn_conn.py` and `azure_sas_conn.py` ignore the `bucket`
parameter in all storage operations (`put`, `get`, `rm`, `obj_exist`,
`get_presigned_url`). Files are stored flat using only the filename, so
two datasets containing a file with the same name will overwrite each
other.
The MinIO and S3 implementations correctly use the bucket (typically the
knowledge base ID) as a path prefix to create logical folder isolation:
- MinIO: uses `use_prefix_path` decorator → `{orig_bucket}/{fnm}`
- S3: uses `use_prefix_path` decorator → `{prefix_path}/{bucket}/{fnm}`
## Fix
Prepend `{bucket}/` to the file path in all 5 operations across both
Azure connector files:
| File | Methods fixed |
|------|---------------|
| `azure_spn_conn.py` | `put`, `get`, `rm`, `obj_exist`,
`get_presigned_url` |
| `azure_sas_conn.py` | `put`, `get`, `rm`, `obj_exist`,
`get_presigned_url` |
This matches the existing convention where `bucket` is the knowledge
base ID used as a directory prefix.
## ⚠️ Migration Note
Existing Azure SPN/SAS deployments have files stored without the bucket
prefix. After this fix, new files will be stored under
`{bucket}/{filename}` while existing files remain at `{filename}`. A
one-time migration script or manual file move may be needed for existing
deployments. New deployments are unaffected.
## Testing
- Verified the fix is consistent across all 5 methods in both files
- The `health()` method is intentionally left unchanged as it uses a
hardcoded test filename without bucket semantics
Co-authored-by: Jin Hai <haijin.chn@gmail.com>
2026-05-07 20:48:32 +08:00
|
|
|
logging.exception(f"fail get {blob_name}")
|
2024-09-09 09:41:14 +08:00
|
|
|
self.__open__()
|
|
|
|
|
time.sleep(1)
|
2026-05-08 12:06:28 +08:00
|
|
|
return None
|
2024-09-09 09:41:14 +08:00
|
|
|
|
|
|
|
|
def obj_exist(self, bucket, fnm):
|
2026-05-08 12:06:28 +08:00
|
|
|
blob_name = f"{bucket}/{fnm}"
|
2024-09-09 09:41:14 +08:00
|
|
|
try:
|
2026-05-08 12:06:28 +08:00
|
|
|
return self.conn.get_blob_client(f"{blob_name}").exists()
|
2024-11-12 17:35:13 +08:00
|
|
|
except Exception:
|
2026-05-08 12:06:28 +08:00
|
|
|
logging.exception(f"Fail put {blob_name}")
|
2024-09-09 09:41:14 +08:00
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
def get_presigned_url(self, bucket, fnm, expires):
|
fix: prepend bucket prefix to Azure SPN and SAS storage paths (#14185)
## Summary
Fixes #14159 — files from different datasets can overwrite each other in
Azure Blob storage.
## Problem
Both `azure_spn_conn.py` and `azure_sas_conn.py` ignore the `bucket`
parameter in all storage operations (`put`, `get`, `rm`, `obj_exist`,
`get_presigned_url`). Files are stored flat using only the filename, so
two datasets containing a file with the same name will overwrite each
other.
The MinIO and S3 implementations correctly use the bucket (typically the
knowledge base ID) as a path prefix to create logical folder isolation:
- MinIO: uses `use_prefix_path` decorator → `{orig_bucket}/{fnm}`
- S3: uses `use_prefix_path` decorator → `{prefix_path}/{bucket}/{fnm}`
## Fix
Prepend `{bucket}/` to the file path in all 5 operations across both
Azure connector files:
| File | Methods fixed |
|------|---------------|
| `azure_spn_conn.py` | `put`, `get`, `rm`, `obj_exist`,
`get_presigned_url` |
| `azure_sas_conn.py` | `put`, `get`, `rm`, `obj_exist`,
`get_presigned_url` |
This matches the existing convention where `bucket` is the knowledge
base ID used as a directory prefix.
## ⚠️ Migration Note
Existing Azure SPN/SAS deployments have files stored without the bucket
prefix. After this fix, new files will be stored under
`{bucket}/{filename}` while existing files remain at `{filename}`. A
one-time migration script or manual file move may be needed for existing
deployments. New deployments are unaffected.
## Testing
- Verified the fix is consistent across all 5 methods in both files
- The `health()` method is intentionally left unchanged as it uses a
hardcoded test filename without bucket semantics
Co-authored-by: Jin Hai <haijin.chn@gmail.com>
2026-05-07 20:48:32 +08:00
|
|
|
blob_name = f"{bucket}/{fnm}"
|
2024-09-09 09:41:14 +08:00
|
|
|
for _ in range(10):
|
|
|
|
|
try:
|
fix: prepend bucket prefix to Azure SPN and SAS storage paths (#14185)
## Summary
Fixes #14159 — files from different datasets can overwrite each other in
Azure Blob storage.
## Problem
Both `azure_spn_conn.py` and `azure_sas_conn.py` ignore the `bucket`
parameter in all storage operations (`put`, `get`, `rm`, `obj_exist`,
`get_presigned_url`). Files are stored flat using only the filename, so
two datasets containing a file with the same name will overwrite each
other.
The MinIO and S3 implementations correctly use the bucket (typically the
knowledge base ID) as a path prefix to create logical folder isolation:
- MinIO: uses `use_prefix_path` decorator → `{orig_bucket}/{fnm}`
- S3: uses `use_prefix_path` decorator → `{prefix_path}/{bucket}/{fnm}`
## Fix
Prepend `{bucket}/` to the file path in all 5 operations across both
Azure connector files:
| File | Methods fixed |
|------|---------------|
| `azure_spn_conn.py` | `put`, `get`, `rm`, `obj_exist`,
`get_presigned_url` |
| `azure_sas_conn.py` | `put`, `get`, `rm`, `obj_exist`,
`get_presigned_url` |
This matches the existing convention where `bucket` is the knowledge
base ID used as a directory prefix.
## ⚠️ Migration Note
Existing Azure SPN/SAS deployments have files stored without the bucket
prefix. After this fix, new files will be stored under
`{bucket}/{filename}` while existing files remain at `{filename}`. A
one-time migration script or manual file move may be needed for existing
deployments. New deployments are unaffected.
## Testing
- Verified the fix is consistent across all 5 methods in both files
- The `health()` method is intentionally left unchanged as it uses a
hardcoded test filename without bucket semantics
Co-authored-by: Jin Hai <haijin.chn@gmail.com>
2026-05-07 20:48:32 +08:00
|
|
|
return self.conn.get_presigned_url("GET", bucket, blob_name, expires)
|
2024-11-12 17:35:13 +08:00
|
|
|
except Exception:
|
fix: prepend bucket prefix to Azure SPN and SAS storage paths (#14185)
## Summary
Fixes #14159 — files from different datasets can overwrite each other in
Azure Blob storage.
## Problem
Both `azure_spn_conn.py` and `azure_sas_conn.py` ignore the `bucket`
parameter in all storage operations (`put`, `get`, `rm`, `obj_exist`,
`get_presigned_url`). Files are stored flat using only the filename, so
two datasets containing a file with the same name will overwrite each
other.
The MinIO and S3 implementations correctly use the bucket (typically the
knowledge base ID) as a path prefix to create logical folder isolation:
- MinIO: uses `use_prefix_path` decorator → `{orig_bucket}/{fnm}`
- S3: uses `use_prefix_path` decorator → `{prefix_path}/{bucket}/{fnm}`
## Fix
Prepend `{bucket}/` to the file path in all 5 operations across both
Azure connector files:
| File | Methods fixed |
|------|---------------|
| `azure_spn_conn.py` | `put`, `get`, `rm`, `obj_exist`,
`get_presigned_url` |
| `azure_sas_conn.py` | `put`, `get`, `rm`, `obj_exist`,
`get_presigned_url` |
This matches the existing convention where `bucket` is the knowledge
base ID used as a directory prefix.
## ⚠️ Migration Note
Existing Azure SPN/SAS deployments have files stored without the bucket
prefix. After this fix, new files will be stored under
`{bucket}/{filename}` while existing files remain at `{filename}`. A
one-time migration script or manual file move may be needed for existing
deployments. New deployments are unaffected.
## Testing
- Verified the fix is consistent across all 5 methods in both files
- The `health()` method is intentionally left unchanged as it uses a
hardcoded test filename without bucket semantics
Co-authored-by: Jin Hai <haijin.chn@gmail.com>
2026-05-07 20:48:32 +08:00
|
|
|
logging.exception(f"fail get {blob_name}")
|
2024-09-09 09:41:14 +08:00
|
|
|
self.__open__()
|
|
|
|
|
time.sleep(1)
|
2026-05-08 12:06:28 +08:00
|
|
|
return None
|