syneto_api 0.2.45__tar.gz → 0.2.47__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: syneto-api
3
- Version: 0.2.45
3
+ Version: 0.2.47
4
4
  Summary: Syneto Client API library
5
5
  Home-page: https://github.com/SynetoNet/syneto-api
6
6
  License: Proprietary
@@ -11,6 +11,9 @@ Classifier: License :: Other/Proprietary License
11
11
  Classifier: Programming Language :: Python :: 3
12
12
  Classifier: Programming Language :: Python :: 3.7
13
13
  Classifier: Programming Language :: Python :: 3.8
14
+ Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
14
17
  Requires-Dist: aiodns (>=3,<4)
15
18
  Requires-Dist: aiohttp (>=3.7,<4.0)
16
19
  Requires-Dist: cchardet (>=2.1,<3.0)
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "syneto_api"
3
- version = "0.2.45"
3
+ version = "0.2.47"
4
4
  description = "Syneto Client API library"
5
5
  authors = ["Your Name <you@example.com>"]
6
6
  license = "Proprietary"
@@ -21,13 +21,13 @@ install_requires = \
21
21
 
22
22
  setup_kwargs = {
23
23
  'name': 'syneto-api',
24
- 'version': '0.2.45',
24
+ 'version': '0.2.47',
25
25
  'description': 'Syneto Client API library',
26
26
  'long_description': '# Syneto API\n\nSyneto Client API library: authentication, storage, virtualization and protection\n\n# Installation\n\n```\n$ pip install syneto-api\n```\n\n# Basic Usage\n\n```\nfrom syneto_api import Authentication, Virtualization, Storage, Protection\n\nauth_api = Authentication(url_base="https://syneto-instance-ip-address/api/auth", insecure_ssl=True)\nresponse = auth_api.login(username="admin", password="admin")\njwt = response[\'jwt\']\n\nvirt_api = Virtualization(url_base="https://syneto-instance-ip-address/api/virtualization", insecure_ssl=True)\nvirt_api.set_auth_jwt(jwt)\nprint(virt_api.get_vms())\n\nstorage_api = Storage(url_base="https://syneto-instance-ip-address/api/storage", insecure_ssl=True)\nstorage_api.set_auth_jwt(jwt)\nprint(storage_api.get_pools())\n```\n\n# Environment Variables\n\nFor conveninence, the base urls for the api endpoints are also accepted as environment variables, please see below.\n\n```\nAUTH_SERVICE=https://syneto-instance-ip-address/api/auth\nVIRTUALIZATION_SERVICE=https://syneto-instance-ip-address/api/virtualization\nSTORAGE_SERVICE=https://syneto-instance-ip-address/api/storage\nPROTECTION_SERVICE=https://syneto-instance-ip-address/api/protection\n```\n\nIf you are using self-signed SSL certificates, set the following env. so that the http request library does not perform ssl verification. \n\n```\nALLOW_INSECURE_SSL=True\n```\n',
27
27
  'author': 'Your Name',
28
28
  'author_email': 'you@example.com',
29
- 'maintainer': None,
30
- 'maintainer_email': None,
29
+ 'maintainer': 'None',
30
+ 'maintainer_email': 'None',
31
31
  'url': 'https://github.com/SynetoNet/syneto-api',
32
32
  'package_dir': package_dir,
33
33
  'packages': packages,
@@ -5,3 +5,4 @@ from .storage_api import Storage
5
5
  from .protection_api import Protection
6
6
  from .jobs_api import Jobs
7
7
  from .central_api import Central
8
+ from .node_api import Node
@@ -7,7 +7,7 @@ import logging
7
7
  import traceback
8
8
  import urllib.parse
9
9
  import concurrent.futures as futures
10
- from tenacity import Retrying, AsyncRetrying, RetryError, stop_after_delay
10
+ from tenacity import Retrying, AsyncRetrying, RetryError, stop_after_delay, retry_if_not_exception_type
11
11
 
12
12
  from .settings import get_env_flag
13
13
  from .keyring import KeyRing
@@ -104,7 +104,9 @@ class APIClientBase:
104
104
  ):
105
105
  try:
106
106
  logger.debug(f"Calling {method} {url} with aiohttp lib")
107
- async for attempt in AsyncRetrying(stop=stop_after_delay(self.timeout), reraise=True):
107
+ async for attempt in AsyncRetrying(
108
+ stop=stop_after_delay(self.timeout), retry=retry_if_not_exception_type(APIException), reraise=True
109
+ ):
108
110
  with attempt:
109
111
  return await asyncio.wait_for(
110
112
  self._unsafe_async_request(
@@ -194,7 +196,9 @@ class APIClientBase:
194
196
  ):
195
197
  try:
196
198
  logger.debug(f"Calling {method} {url} with requests lib")
197
- for attempt in Retrying(stop=stop_after_delay(self.timeout), reraise=True):
199
+ for attempt in Retrying(
200
+ stop=stop_after_delay(self.timeout), retry=retry_if_not_exception_type(APIException), reraise=True
201
+ ):
198
202
  with attempt:
199
203
  return self._unsafe_sync_request(
200
204
  method, url, body, success_codes, error_subject, on_response_callback
@@ -0,0 +1,74 @@
1
+ import os
2
+ from .api_client import APIClientBase
3
+
4
+
5
+ class Node(APIClientBase):
6
+ def __init__(self, url_base=None, **kwargs):
7
+ super().__init__(url_base or os.environ.get("PROTECTION_SERVICE", ""), **kwargs)
8
+
9
+ def get_installed_version(self):
10
+ return self.get_request("/software/installed")
11
+
12
+ def get_available_upgrade_versions(self):
13
+ return self.get_request("/software/available")
14
+
15
+ def check_available_updates(self):
16
+ return self.post_request("/software/available")
17
+
18
+ def get_update_job(self):
19
+ return self.get_request("/software/update")
20
+
21
+ def start_update_job(self, upgrade_branch: str, upgrade_channel: str, enable_hotfix_channels: bool = False, enable_dev_channels: bool = False):
22
+ body = {
23
+ "upgradeBranch": upgrade_branch,
24
+ "upgradeChannel": upgrade_channel,
25
+ "enableHotfixChannels": enable_hotfix_channels,
26
+ "enableDevChannels": enable_dev_channels,
27
+ }
28
+ return self.post_request("/software/update", body=body)
29
+
30
+ def update_job_acknowledge(self):
31
+ return self.put_request("/software/update/acknowledge")
32
+
33
+ def get_system_details(self):
34
+ return self.get_request("/system")
35
+
36
+ def get_system_health(self):
37
+ return self.get_request("/health")
38
+
39
+ def get_time(self):
40
+ return self.get_request("/time")
41
+
42
+ def set_time(self, date:str, timezone:str, require_reboot: bool, ntp: dict):
43
+ body = {
44
+ "date": date,
45
+ "timezone": timezone,
46
+ "requireReboot": require_reboot,
47
+ "ntp": ntp,
48
+ }
49
+ return self.post_request("/time", body=body)
50
+
51
+ def get_available_timezones(self):
52
+ return self.get_request("/time/timezones")
53
+
54
+ def sync_clock_with_ntp(self, require_reboot: bool = False):
55
+ body = {
56
+ "requireReboot": require_reboot,
57
+ }
58
+ return self.put_request("/time/ntp/sync-clock", body=body)
59
+
60
+ def reboot_host(self):
61
+ return self.put_request("/reboot")
62
+
63
+ def poweroff_host(self):
64
+ return self.put_request("/poweroff")
65
+
66
+ def add_user_event(self, _type: str, client_time: str, order: int, properties: dict):
67
+ body = {
68
+ "type": _type,
69
+ "clientTime": client_time,
70
+ "order": order,
71
+ "properties": properties,
72
+ }
73
+ return self.post_request("/bond/user-events", body=body)
74
+
@@ -80,9 +80,17 @@ class Storage(APIClientBase):
80
80
  "/volumes/{volume_id}/snapshots", volume_id=volume_id, query_args={"snapshot_name": snapshot_name}
81
81
  )
82
82
 
83
+ def get_volume_changes(self, volume_id: str, snapshot_name: str):
84
+ return self.post_request(
85
+ "/volumes/{volume_id}/changes",
86
+ volume_id=volume_id,
87
+ body={"volume_id": volume_id, "snapshot_name": snapshot_name},
88
+ )
89
+
83
90
  def get_volume_snapshot(self, volume_id: str, snapshot_name: str):
84
91
  return self.get_request(
85
- "/volumes/{volume_id}/snapshots/{snapshot_name}", volume_id=volume_id, snapshot_name=snapshot_name
92
+ "/volumes/{volume_id}/snapshots/{snapshot_name}",
93
+ volume_id=volume_id,
86
94
  )
87
95
 
88
96
  def remove_volume_snapshot(self, volume_id: str, snapshot_name: str):
@@ -34,6 +34,9 @@ class Virtualization(APIClientBase):
34
34
  snapshots = self.get_request("/vmware/vms/{vm_syn_id}/snapshots", vm_syn_id=vm_syn_id)
35
35
  return next((snap for snap in snapshots if snap["name"] == snapshot_name), None)
36
36
 
37
+ def get_vm_snapshots(self, vm_syn_id: str):
38
+ return self.get_request("/vmware/vms/{vm_syn_id}/snapshots", vm_syn_id=vm_syn_id)
39
+
37
40
  def create_vm_snapshot(
38
41
  self, vm_syn_id: str, snapshot_name: str, quiesce: bool = True, dumpmem: bool = False,
39
42
  ):
@@ -80,3 +83,21 @@ class Virtualization(APIClientBase):
80
83
  "/vmware/datastores",
81
84
  query_args={"datastore_syn_id": syn_id if syn_id else "", "datastore_mountpoint": mountpoint},
82
85
  )
86
+
87
+ def get_virtual_machine_cbt_info(self, vm_syn_id: str):
88
+ return self.get_request("/vmware/vms/{vm_syn_id}/cbt", vm_syn_id=vm_syn_id)
89
+
90
+ def enable_virtual_machine_cbt(self, vm_syn_id: str):
91
+ return self.put_request(
92
+ "/vmware/vms/{vm_syn_id}/cbt",
93
+ vm_syn_id=vm_syn_id,
94
+ query_args={"action": "enable_cbt"},
95
+ body={},
96
+ success_codes=[200, 409, 500],
97
+ )
98
+
99
+ def get_vm_snapshot_by_ref(self, vm_syn_id: str, snapshot_ref: str):
100
+ return self.get_request(
101
+ "/vmware/vms/{vm_syn_id}/snapshots/{snapshot_ref}", vm_syn_id=vm_syn_id, snapshot_ref=snapshot_ref
102
+ )
103
+
File without changes