Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

backup task created from cloud #8972

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 30 additions & 2 deletions cvat/apps/engine/backup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import os
import re
import shutil
import tempfile
import uuid
from abc import ABCMeta, abstractmethod
from collections.abc import Collection, Iterable
Expand Down Expand Up @@ -46,7 +47,10 @@
retry_current_rq_job,
)
from cvat.apps.engine import models
from cvat.apps.engine.cloud_provider import import_resource_from_cloud_storage
from cvat.apps.engine.cloud_provider import (
db_storage_to_storage_instance,
import_resource_from_cloud_storage,
)
from cvat.apps.engine.location import StorageType, get_location_configuration
from cvat.apps.engine.log import ServerLogManager
from cvat.apps.engine.models import (
Expand Down Expand Up @@ -439,8 +443,29 @@ def _write_data(self, zip_object, target_dir=None):
files=[self._db_data.get_manifest_path()],
target_dir=target_data_dir,
)
elif self._db_data.storage == StorageChoice.CLOUD_STORAGE:
assert not hasattr(self._db_data, 'video'), "Only images can be stored in cloud storage"
media_files = [im.path for im in self._db_data.images.all()]
cloud_storage_instance = db_storage_to_storage_instance(self._db_data.cloud_storage)
with tempfile.TemporaryDirectory() as tmp_dir:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Images can be:

  • 2d and 3d
  • raw and archive

There can also be related images. Probably, they are not included.

Please check these cases.

cloud_storage_instance.bulk_download_to_dir(files=media_files, upload_dir=tmp_dir)
self._write_files(
source_dir=tmp_dir,
zip_object=zip_object,
files=[
os.path.join(tmp_dir, file)
for file in media_files
],
target_dir=target_data_dir,
)
self._write_files(
source_dir=self._db_data.get_upload_dirname(),
zip_object=zip_object,
files=[self._db_data.get_manifest_path()],
target_dir=target_data_dir,
)
else:
raise NotImplementedError("We don't currently support backing up tasks with data from cloud storage")
raise NotImplementedError

def _write_task(self, zip_object, target_dir=None):
task_dir = self._db_task.get_dirname()
Expand Down Expand Up @@ -539,6 +564,9 @@ def serialize_data():
]
data['validation_layout'] = validation_params

if self._db_data.storage == StorageChoice.CLOUD_STORAGE:
data["storage"] = StorageChoice.LOCAL

return self._prepare_data_meta(data)

task = serialize_task()
Expand Down
27 changes: 27 additions & 0 deletions tests/python/rest_api/test_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -3959,6 +3959,33 @@ def test_cannot_export_backup_for_task_without_data(self, tasks):
assert exc.status == HTTPStatus.BAD_REQUEST
assert "Backup of a task without data is not allowed" == exc.body.encode()

def test_can_export_and_import_backup_task_with_cloud_storage(self, tasks):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add tests for video and 3d data, with and without static chunks? Maybe it will be more convenient to do this in server unit tests.

cloud_storage_content = ["image_case_65_1.png", "image_case_65_2.png"]
task_spec = {
"name": "Task with files from cloud storage",
"labels": [
{
"name": "car",
}
],
}
data_spec = {
"image_quality": 75,
"use_cache": False,
"cloud_storage_id": 1,
"server_files": cloud_storage_content,
}
task_id, _ = create_task(self.user, task_spec, data_spec)

task = self.client.tasks.retrieve(task_id)

filename = self.tmp_dir / f"cloud_task_{task.id}_backup.zip"
task.download_backup(filename)

assert filename.is_file()
assert filename.stat().st_size > 0
self._test_can_restore_task_from_backup(task_id)

@pytest.mark.parametrize("mode", ["annotation", "interpolation"])
def test_can_import_backup(self, tasks, mode):
task_id = next(t for t in tasks if t["mode"] == mode)["id"]
Expand Down
Loading