Skip to content
Merged
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
3 changes: 1 addition & 2 deletions synology_dsm/api/storage/storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,7 @@ def _get_disk(self, disk_id):
def _get_disks_for_volume(self, volume_id):
"""Returns a list of disk for a specific volume."""
disks = []
pools = self._data.get("storagePools", [])
for pool in pools:
for pool in self.storage_pools:
if pool["deploy_path"] == volume_id:
for disk_id in pool["disks"]:
disks.append(self._get_disk(disk_id))
Expand Down
37 changes: 25 additions & 12 deletions synology_dsm/synology_dsm.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ class SynologyDSM(object):
API_INFO = "SYNO.API.Info"
API_AUTH = "SYNO.API.Auth"

DSM_5_WEIRD_URL_API = [
SynoStorage.API_KEY,
]

def __init__(
self,
dsm_ip,
Expand Down Expand Up @@ -74,16 +78,22 @@ def _debuglog(self, message):
if self._debugmode:
print("DEBUG: " + message)

def _build_url(self, api):
if (
api == SynoStorage.API_KEY
def _is_weird_api_url(self, api):
"""Returns True if the API URL is not common (nas_base_url/webapi/path?params) [Only handles DSM 5 for now]."""
return (
api in self.DSM_5_WEIRD_URL_API
and self._information
and self._information.version
and int(self._information.version) < 7321 # < DSM 6
):
return (
"%s/webman/modules/StorageManager/storagehandler.cgi?" % self._base_url
)
)

def _build_url(self, api):
if self._is_weird_api_url(api):
if api == SynoStorage.API_KEY:
return (
"%s/webman/modules/StorageManager/storagehandler.cgi?"
% self._base_url
)

return "%s/webapi/%s?" % (self._base_url, self.apis[api]["path"])

Expand Down Expand Up @@ -176,15 +186,18 @@ def _request(
if not self._session_id and api not in [self.API_AUTH, self.API_INFO]:
self.login()

# Check if API is available
if not self.apis.get(api):
raise SynologyDSMAPINotExistsException(api)

# Build request params
if not params:
params = {}
params["api"] = api
params["version"] = self.apis[api]["maxVersion"]
params["version"] = 1

if not self._is_weird_api_url(api):
# Check if API is available
if not self.apis.get(api):
raise SynologyDSMAPINotExistsException(api)
params["version"] = self.apis[api]["maxVersion"]

params["method"] = method

if api == SynoStorage.API_KEY:
Expand Down
54 changes: 44 additions & 10 deletions tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,37 @@
DSM_6_CORE_UTILIZATION,
DSM_6_STORAGE_STORAGE,
)
from .api_data.dsm_5 import (
DSM_5_API_INFO,
DSM_5_AUTH_LOGIN,
DSM_5_AUTH_LOGIN_2SA,
DSM_5_AUTH_LOGIN_2SA_OTP,
DSM_5_DSM_INFORMATION,
DSM_5_CORE_UTILIZATION,
DSM_5_STORAGE_STORAGE,
)

API_SWITCHER = {
5: {
"API_INFO": DSM_5_API_INFO,
"AUTH_LOGIN": DSM_5_AUTH_LOGIN,
"AUTH_LOGIN_2SA": DSM_5_AUTH_LOGIN_2SA,
"AUTH_LOGIN_2SA_OTP": DSM_5_AUTH_LOGIN_2SA_OTP,
"DSM_INFORMATION": DSM_5_DSM_INFORMATION,
"CORE_UTILIZATION": DSM_5_CORE_UTILIZATION,
"STORAGE_STORAGE": DSM_5_STORAGE_STORAGE,
},
6: {
"API_INFO": DSM_6_API_INFO,
"AUTH_LOGIN": DSM_6_AUTH_LOGIN,
"AUTH_LOGIN_2SA": DSM_6_AUTH_LOGIN_2SA,
"AUTH_LOGIN_2SA_OTP": DSM_6_AUTH_LOGIN_2SA_OTP,
"DSM_INFORMATION": DSM_6_DSM_INFORMATION,
"CORE_UTILIZATION": DSM_6_CORE_UTILIZATION,
"STORAGE_STORAGE": DSM_6_STORAGE_STORAGE,
},
}


if six.PY2:
from future.moves.urllib.parse import urlencode
Expand All @@ -43,7 +74,7 @@
class SynologyDSMMock(SynologyDSM):
"""Mocked SynologyDSM."""

API_URI = "entry.cgi"
API_URI = "api="

def __init__(
self,
Expand All @@ -66,8 +97,11 @@ def __init__(
debugmode,
)

self.dsm_version = 6

def _execute_request(self, method, url, **kwargs):
url += urlencode(kwargs["params"])

if "no_internet" in url:
raise SynologyDSMRequestException(
ConnError(
Expand Down Expand Up @@ -98,38 +132,38 @@ def _execute_request(self, method, url, **kwargs):
raise SynologyDSMRequestException(RequestException("Bad request"))

if self.API_INFO in url:
return DSM_6_API_INFO
return API_SWITCHER[self.dsm_version]["API_INFO"]

if self.API_AUTH in url:
if VALID_USER_2SA in url and VALID_PASSWORD in url:
if "otp_code" not in url and "device_id" not in url:
return DSM_6_AUTH_LOGIN_2SA
return API_SWITCHER[self.dsm_version]["AUTH_LOGIN_2SA"]

if "device_id" in url and DEVICE_TOKEN in url:
return DSM_6_AUTH_LOGIN
return API_SWITCHER[self.dsm_version]["AUTH_LOGIN"]

if "otp_code" in url:
if VALID_OTP in url:
return DSM_6_AUTH_LOGIN_2SA_OTP
return API_SWITCHER[self.dsm_version]["AUTH_LOGIN_2SA_OTP"]
return ERROR_AUTH_OTP_AUTHENTICATE_FAILED

if VALID_USER in url and VALID_PASSWORD in url:
return DSM_6_AUTH_LOGIN
return API_SWITCHER[self.dsm_version]["AUTH_LOGIN"]

return ERROR_AUTH_INVALID_CREDENTIALS

if self.API_URI in url:
if not self._session_id or not self._syno_token:
if not self._session_id:
return ERROR_INSUFFICIENT_USER_PRIVILEGE

if SynoDSMInformation.API_KEY in url:
return DSM_6_DSM_INFORMATION
return API_SWITCHER[self.dsm_version]["DSM_INFORMATION"]

if SynoCoreUtilization.API_KEY in url:
return DSM_6_CORE_UTILIZATION
return API_SWITCHER[self.dsm_version]["CORE_UTILIZATION"]

if SynoStorage.API_KEY in url:
return DSM_6_STORAGE_STORAGE
return API_SWITCHER[self.dsm_version]["STORAGE_STORAGE"]

if (
"SYNO.FileStation.Upload" in url
Expand Down
15 changes: 10 additions & 5 deletions tests/api_data/dsm_5/const_5_api_auth.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
"""DSM 5 SYNO.API.Auth data."""
from tests.const import ( # pylint: disable=unused-import
from tests.const import (
SESSION_ID,
DEVICE_TOKEN,
SYNO_TOKEN,
ERROR_AUTH_OTP_NOT_SPECIFIED,
)


DSM_5_AUTH_LOGIN = {}
# No synotoken for an unknown reason
DSM_5_AUTH_LOGIN = {
"data": {"is_portal_port": False, "sid": SESSION_ID},
"success": True,
}
DSM_5_AUTH_LOGIN_2SA = ERROR_AUTH_OTP_NOT_SPECIFIED
DSM_5_AUTH_LOGIN_2SA_OTP = {}
DSM_5_AUTH_LOGIN_2SA_OTP = {
"data": {"did": DEVICE_TOKEN, "is_portal_port": False, "sid": SESSION_ID},
"success": True,
}
Loading