This commit is contained in:
Victor Alexandrovich Tsyrenschikov
2025-07-16 01:02:10 +05:00
parent 0fc5b15016
commit ab5d6bf686
28 changed files with 12103 additions and 0 deletions

261
synology_api/snapshot.py Normal file
View File

@@ -0,0 +1,261 @@
from __future__ import annotations
from typing import Optional
from . import base_api
import json
class Snapshot(base_api.BaseApi):
"""Class for interacting with Snapshot APIs.
This class implements APIs to manage snapshots.
There is no documentation for these APIs, so the implementation is based on network inspection.
Examples
--------
List snapshots for a share:
>>> from synology_api import snapshot
>>> ss = snapshot.Snapshot('IP', 'PORT', 'USER', 'PASSWORD')
>>> resp = ss.list_snapshots('share_name')
>>> print(resp)
Create a snapshot for a share:
>>> resp = ss.create_snapshot('share_name')
>>> print(resp)
Delete snapshots for a share:
>>> resp = ss.delete_snapshots('share_name', ['snapshot_name'])
>>> print(resp)
Set attributes for a snapshot:
>>> resp = ss.set_snapshot_attr('share_name', 'snapshot_name', description='new description', lock=True)
>>> print(resp)
"""
def list_snapshots(self,
share_name: str,
attribute_filter: list[str] = [],
additional_attribute: list[str] = [],
offset: int = 0,
limit: int = -1) -> dict[str, object] | str:
"""List snapshots for a share.
Parameters
----------
share_name : str
Name of the share to list snapshots for
attribute_filter : list[str], optional
List of attributes filter to apply. Defaults to [] (no filter).
Each attribute filter is a string in the format of "attr==value" or "attr=value" and
optionally prefixed with "!" to negate the filter.
The following are examples of valid attribute filters:
- ["!hide==true", "desc==abc"] # hide is not true and desc is exactly abc
- ["desc=abc"] # desc has abc in it
additional_attribute : list[str], optional
List of snapshot attributes whose values are included in the response.
Defaults to [] (only time is returned).
Note that not all attributes are available via API. The following are confirmed to work:
- desc
- lock
- worm_lock
- schedule_snapshot
offset : int, optional
Offset to start listing from. Defaults to 0.
limit : int, optional
Number of snapshots to return. Defaults to -1 (all).
Returns
-------
dict[str, object] | str
API response if successful, error message if not
Example:
{
"data": {
"snapshots": [
{
"desc": "",
"lock": true,
"schedule_snapshot": false,
"time": "GMT+09-2023.09.11-23.23.40",
"worm_lock": true,
"worm_lock_begin": "1694442321",
"worm_lock_day": "1",
"worm_lock_end": "1694528721"
}
],
"total": 1
},
"success": true
}
"""
api_name = 'SYNO.Core.Share.Snapshot'
info = self.gen_list[api_name]
api_path = info['path']
req_param = {'version': '2',
'method': 'list',
'name': share_name,
'filter': json.dumps({"attr": attribute_filter}),
'additional': json.dumps(additional_attribute),
'offset': offset,
'limit': limit}
return self.request_data(api_name, api_path, req_param)
def create_snapshot(self,
share_name: str,
description: str = "",
lock: bool = False,
immutable: bool = False,
immutable_days: int = 7,
) -> dict[str, object] | str:
"""Create a snapshot for a share.
Parameters
----------
share_name : str
Name of the share to create a snapshot for
description : str, optional
Description of the snapshot. Defaults to "".
lock : bool, optional
Whether to lock the snapshot. Defaults to False.
immutable : bool, optional
Whether to make the snapshot immutable. Defaults to False.
immutable_days : int, optional
Number of days to make the snapshot immutable for. Defaults to 7.
Must be greater than 0. Mandatory if immutable is True.
Returns
-------
dict[str, object] | str
API response if successful, error message if not
Example:
{
"data": "GMT+09-2023.09.12-00.33.20",
"success": true
}
"""
api_name = 'SYNO.Core.Share.Snapshot'
info = self.gen_list[api_name]
api_path = info['path']
snapinfo = {
"desc": description,
"lock": lock,
}
if immutable == True:
snapinfo['worm_lock'] = True
if immutable_days < 1:
return "immutable_days must be greater than 0"
snapinfo['worm_lock_day'] = immutable_days
req_param = {'version': '1',
'method': 'create',
'snapinfo': json.dumps(snapinfo),
'name': share_name}
return self.request_data(api_name, api_path, req_param)
def delete_snapshots(self,
share_name: str,
snapshots: list[str]
) -> dict[str, object] | str:
"""Delete snapshots for a share.
Parameters
----------
share_name : str
Name of the share to delete snapshots for
snapshots : list[str]
List of snapshots to delete
Returns
-------
dict[str, object] | str
API response if successful, error message if not
Example:
{
"success": true
}
"""
api_name = 'SYNO.Core.Share.Snapshot'
info = self.gen_list[api_name]
api_path = info['path']
req_param = {'version': '1',
'method': 'delete',
'name': share_name,
'snapshots': json.dumps(snapshots)}
return self.request_data(api_name, api_path, req_param)
def set_snapshot_attr(self,
share_name: str,
snapshot: str,
description: Optional[str] = None,
lock: Optional[bool] = None,
immutable: Optional[bool] = None,
immutable_days: Optional[int] = None
) -> dict[str, object] | str:
"""Set attributes for a snapshot.
Parameters
----------
share_name : str
Name of the share to set attributes for
snapshot : str
Name of the snapshot to set attributes for
description : str, optional
Description of the snapshot. Defaults to None (no change).
lock : bool, optional
Whether to lock the snapshot. Defaults to None (no change).
immutable : bool, optional
Whether to make the snapshot immutable. Defaults to None (no change).
immutable_days : int, optional
Number of days to make the snapshot immutable for. Defaults to None (no change).
Must be greater than 0. Mandatory if immutable is True.
Returns
-------
dict[str, object] | str
API response if successful, error message if not
Example:
{
"success": true
}
"""
api_name = 'SYNO.Core.Share.Snapshot'
info = self.gen_list[api_name]
api_path = info['path']
snapinfo = {}
if description is not None:
snapinfo['desc'] = description
if lock is not None:
snapinfo['lock'] = lock
if immutable is not None:
if immutable == False:
return "immutable cannot be set to False"
if immutable_days is None:
return "immutable_days must be specified if immutable is True"
if immutable_days < 1:
return "immutable_days must be greater than 0"
snapinfo['worm_lock'] = True
snapinfo['worm_lock_day'] = immutable_days
req_param = {'version': '1',
'method': 'set',
'snapinfo': json.dumps(snapinfo),
'name': share_name,
'snapshot': snapshot}
return self.request_data(api_name, api_path, req_param)