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

refactor: re-define vfolder delete status #1892

Merged
merged 27 commits into from
Feb 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
d0df459
refactor: re-define vfolder delete status
fregataa Feb 6, 2024
6aca728
add news fragment
fregataa Feb 6, 2024
7f77f10
update news fragment
fregataa Feb 6, 2024
c7b9a85
update status_chaged field
fregataa Feb 6, 2024
f75f57b
remove keypair_resource_policy max_vfolder_count check in restore
fregataa Feb 6, 2024
cd3b660
apply status change in ensure API
fregataa Feb 7, 2024
8f30f80
rename recover to restore
fregataa Feb 7, 2024
eedc0a3
revert cli recover cmd and add restore cmd
fregataa Feb 7, 2024
e1e02a2
revert recover client API
fregataa Feb 7, 2024
5f8d777
refactor migration code
fregataa Feb 7, 2024
eb905ca
get vfolder id as API params
fregataa Feb 7, 2024
b6d4856
split dead vfolder statuses into soft deleted and hard deleted
fregataa Feb 7, 2024
e2cc68a
Merge branch 'main' into refactor/vfolder-delete-status
fregataa Feb 11, 2024
79d49c5
Merge branch 'main' into refactor/vfolder-delete-status
fregataa Feb 14, 2024
a7f02b7
rename some VFolderAccessStatus enum
fregataa Feb 14, 2024
78c3bbc
update delete_by_id API
fregataa Feb 14, 2024
306f67d
Merge branch 'main' into refactor/vfolder-delete-status
fregataa Feb 14, 2024
8c44a35
do not check duplicate name with hard-deleted vfolder
fregataa Feb 15, 2024
f070fee
update vfolder access status
fregataa Feb 15, 2024
a4f3501
Merge branch 'main' into refactor/vfolder-delete-status
fregataa Feb 15, 2024
7c023f9
revert return SuccessResponseModel response from DELETE API
fregataa Feb 15, 2024
f34f7ec
update CLI
fregataa Feb 15, 2024
3088695
Merge branch 'main' into refactor/vfolder-delete-status
fregataa Feb 16, 2024
84d0491
Merge branch 'main' into refactor/vfolder-delete-status
fregataa Feb 19, 2024
91566f0
Merge branch 'main' into refactor/vfolder-delete-status
fregataa Feb 22, 2024
022d0fa
readonly connection
fregataa Feb 22, 2024
5147a29
update get_vfolder_id params
fregataa Feb 22, 2024
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
1 change: 1 addition & 0 deletions changes/1892.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Re-define vfolder delete status by adding `delete-pending`, `delete-error` vfolder status and set `delete-pending` as trash-bin status and `delete-complete` as hard-delete status.
43 changes: 38 additions & 5 deletions src/ai/backend/client/cli/vfolder.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,9 @@ def create(name, host, group, host_path, usage_mode, permission, quota, cloneabl
@vfolder.command()
@click.argument("name", type=str)
def delete(name):
"""Delete the given virtual folder.
"""Delete the given virtual folder. The virtual folder will be under `delete-pending` status, which means trash-bin.
This operation can be retracted by
calling `recover()`.
calling `restore()`.

\b
NAME: Name of a virtual folder.
Expand Down Expand Up @@ -198,17 +198,50 @@ def purge(name):
sys.exit(ExitCode.FAILURE)


@vfolder.command()
@click.argument("name", type=str)
def delete_trash(name):
"""Delete the given virtual folder's real data. The virtual folder should be under `delete-pending` status, which means trash-bin.
This operation is irreversible!

NAME: Name of a virtual folder.
"""
with Session() as session:
try:
session.VFolder(name).delete_trash()
print_done("Delete completed.")
except Exception as e:
print_error(e)
sys.exit(ExitCode.FAILURE)


@vfolder.command()
@click.argument("name", type=str)
def recover(name):
Copy link
Member

Choose a reason for hiding this comment

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

Let's rename this to restore and keep the alias for backward compatibility.

Copy link
Member Author

Choose a reason for hiding this comment

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

I added restore command right below(line no 236) and left this for backward compatibility.

"""Recover the given virtual folder from deleted status.
"""Restore the given virtual folder from deleted status, Deprecated since 24.03.1; use `restore`

NAME: Name of a virtual folder.
"""
with Session() as session:
try:
session.VFolder(name).restore()
print_done("Restored.")
except Exception as e:
print_error(e)
sys.exit(ExitCode.FAILURE)


@vfolder.command()
@click.argument("name", type=str)
def restore(name):
"""Restore the given virtual folder from deleted status, from trash bin.

NAME: Name of a virtual folder.
"""
with Session() as session:
try:
session.VFolder(name).recover()
print_done("Recovered.")
session.VFolder(name).restore()
print_done("Restored.")
except Exception as e:
print_error(e)
sys.exit(ExitCode.FAILURE)
Expand Down
55 changes: 48 additions & 7 deletions src/ai/backend/client/func/vfolder.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import asyncio
import uuid
from pathlib import Path
from typing import Dict, Mapping, Optional, Sequence, Union
from typing import Any, Dict, Mapping, Optional, Sequence, Union

import aiohttp
import janus
Expand Down Expand Up @@ -47,8 +48,9 @@ class ResponseFailed(Exception):


class VFolder(BaseFunction):
def __init__(self, name: str):
def __init__(self, name: str, id: Optional[uuid.UUID] = None):
self.name = name
self.id = id

@api_function
@classmethod
Expand Down Expand Up @@ -204,6 +206,15 @@ async def paginated_project_list(
page_size=page_size,
)

async def _get_id_by_name(self) -> uuid.UUID:
rqst = Request("GET", "/folders/_/id")
rqst.set_json({
"name": self.name,
})
async with rqst.fetch() as resp:
data = await resp.json()
return uuid.UUID(data["id"])

@api_function
@classmethod
async def list_hosts(cls):
Expand Down Expand Up @@ -238,17 +249,47 @@ async def delete(self):
return {}

@api_function
async def purge(self):
rqst = Request("POST", "/folders/{0}/purge".format(self.name))
async def purge(self) -> Mapping[str, Any]:
if self.id is None:
vfolder_id = await self._get_id_by_name()
self.id = vfolder_id
rqst = Request("POST", "/folders/purge")
rqst.set_json({
"id": self.id.hex,
})
async with rqst.fetch():
return {}

@api_function
async def recover(self):
rqst = Request("POST", "/folders/{0}/recover".format(self.name))
async def _restore(self) -> Mapping[str, Any]:
if self.id is None:
vfolder_id = await self._get_id_by_name()
self.id = vfolder_id
rqst = Request("POST", "/folders/restore-from-trash-bin")
rqst.set_json({
"id": self.id.hex,
})
async with rqst.fetch():
return {}

@api_function
async def recover(self):
return await self._restore()

@api_function
async def restore(self):
return await self._restore()

@api_function
async def delete_trash(self) -> Mapping[str, Any]:
if self.id is None:
vfolder_id = await self._get_id_by_name()
self.id = vfolder_id
rqst = Request("POST", "/folders/delete-from-trash-bin")
rqst.set_json({
"id": self.id.hex,
})
return {}

@api_function
async def rename(self, new_name):
rqst = Request("POST", "/folders/{0}/rename".format(self.name))
Expand Down
Loading
Loading