commit
28678fb8f0
@ -0,0 +1,25 @@
|
|||||||
|
repos:
|
||||||
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
|
rev: v5.0.0
|
||||||
|
hooks:
|
||||||
|
- id: end-of-file-fixer
|
||||||
|
- id: file-contents-sorter
|
||||||
|
files: .*mapping.yml
|
||||||
|
args:
|
||||||
|
- --unique
|
||||||
|
- id: no-commit-to-branch
|
||||||
|
name: no-commit-to-branch (main, master, dev_*)
|
||||||
|
args:
|
||||||
|
- --pattern
|
||||||
|
- dev_.*
|
||||||
|
- repo: https://github.com/pycqa/flake8
|
||||||
|
rev: 7.1.2
|
||||||
|
hooks:
|
||||||
|
- id: flake8
|
||||||
|
name: flake8 (1/2)
|
||||||
|
files: src/dynamix_sdk/types\.py|.*__init__\.py|.*_api\.py
|
||||||
|
args:
|
||||||
|
- --extend-ignore=F401,F403,F405
|
||||||
|
- id: flake8
|
||||||
|
name: flake8 (2/2)
|
||||||
|
exclude: src/dynamix_sdk/types\.py|.*__init__\.py|.*_api\.py
|
@ -0,0 +1,28 @@
|
|||||||
|
# Список изменений в версии 1.0.0
|
||||||
|
|
||||||
|
## Добавлено
|
||||||
|
|
||||||
|
### Глобально
|
||||||
|
| Идентификатор<br>задачи | Описание |
|
||||||
|
| --- | --- |
|
||||||
|
| BPYS-3 | Добавлена возможность авторизации через DECS3O. |
|
||||||
|
| BPYS-7 | Добавлена возможность авторизации через BVS. |
|
||||||
|
|
||||||
|
### Функциональный интерфейс
|
||||||
|
| Идентификатор<br>задачи | Описание |
|
||||||
|
| --- | --- |
|
||||||
|
| BPYS-5 | Добавлена функция API `/system/usermanager/whoami`. |
|
||||||
|
| BPYS-4 | Добавлена функция API `/cloudapi/compute/get`. |
|
||||||
|
| BPYS-6 | Добавлена функция API `/cloudapi/kvmx86/create`. |
|
||||||
|
| BPYS-12 | Добавлена функция API `/cloudapi/compute/delete`. |
|
||||||
|
| BPYS-21 | Добавлена функция API `/cloudapi/user/get`. |
|
||||||
|
| BPYS-15 | Добавлена функция API `/cloudapi/compute/update`. |
|
||||||
|
| BPYS-29 | Добавлена функция API `/cloudapi/account/updateUser`. |
|
||||||
|
| BPYS-33 | Добавлена функция API `/cloudapi/account/enable`. |
|
||||||
|
| BPYS-32 | Добавлена функция API `/cloudapi/account/disable`. |
|
||||||
|
| BPYS-45 | Добавлена функция API `/cloudapi/rg/list`. |
|
||||||
|
| BPYS-20 | Добавлена функция API `/cloudapi/account/addUser`. |
|
||||||
|
| BPYS-30 | Добавлена функция API `/cloudapi/account/deleteUser`. |
|
||||||
|
| BPYS-51 | Добавлена функция API `/cloudapi/rg/get`. |
|
||||||
|
| BPYS-52 | Добавлена функция API `/cloudapi/rg/create`. |
|
||||||
|
| BPYS-35 | Добавлена функция API `/cloudapi/compute/list`. |
|
@ -0,0 +1,4 @@
|
|||||||
|
dev:
|
||||||
|
pip install -e .
|
||||||
|
pip install -r requirements-dev.txt
|
||||||
|
pre-commit install
|
After Width: | Height: | Size: 1.3 MiB |
@ -0,0 +1,27 @@
|
|||||||
|
[project]
|
||||||
|
name = "dynamix-sdk"
|
||||||
|
authors = [{name = "Dmitriy Smirnov"}]
|
||||||
|
version = "1.0.0"
|
||||||
|
|
||||||
|
readme = "README.md"
|
||||||
|
|
||||||
|
requires-python = ">=3.10.12"
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
"requests>=2.32.3",
|
||||||
|
"pydantic>=2.10.5",
|
||||||
|
"pyyaml>=6.0.2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[project.urls]
|
||||||
|
Repository = "https://repository.basistech.ru/BASIS/dynamix-python-sdk"
|
||||||
|
|
||||||
|
[build-system]
|
||||||
|
requires = [
|
||||||
|
"setuptools",
|
||||||
|
"setuptools-scm",
|
||||||
|
]
|
||||||
|
build-backend = "setuptools.build_meta"
|
||||||
|
|
||||||
|
[tool.setuptools.package-data]
|
||||||
|
src = ["*.yml"]
|
@ -0,0 +1 @@
|
|||||||
|
pre-commit==4.1.0
|
@ -0,0 +1,3 @@
|
|||||||
|
from dynamix_sdk.decs3o import DECS3OAuth
|
||||||
|
from dynamix_sdk.bvs import BVSAuth
|
||||||
|
from dynamix_sdk.dynamix import Dynamix
|
@ -0,0 +1,2 @@
|
|||||||
|
from ._api import *
|
||||||
|
from ._nested import *
|
@ -0,0 +1,8 @@
|
|||||||
|
import dynamix_sdk.base as _base
|
||||||
|
from .cloudapi import *
|
||||||
|
from .system import *
|
||||||
|
|
||||||
|
|
||||||
|
class API(_base.BaseAPI):
|
||||||
|
cloudapi: CloudapiAPI
|
||||||
|
system: SystemAPI
|
@ -0,0 +1,3 @@
|
|||||||
|
from .params import *
|
||||||
|
from .result import *
|
||||||
|
from .enums import *
|
@ -0,0 +1,161 @@
|
|||||||
|
from dynamix_sdk.utils import (
|
||||||
|
AutoNameEnum as _AutoNameEnum,
|
||||||
|
enum_auto as _enum_auto,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class AccessType(str, _AutoNameEnum):
|
||||||
|
ARCXDU = _enum_auto()
|
||||||
|
CXDRAU = _enum_auto()
|
||||||
|
RCX = _enum_auto()
|
||||||
|
R = _enum_auto()
|
||||||
|
|
||||||
|
|
||||||
|
class AffinityMode(str, _AutoNameEnum):
|
||||||
|
ANY = _enum_auto()
|
||||||
|
EQ = _enum_auto()
|
||||||
|
NE = _enum_auto()
|
||||||
|
|
||||||
|
|
||||||
|
class AffinityPolicy(str, _AutoNameEnum):
|
||||||
|
RECOMMENDED = _enum_auto()
|
||||||
|
REQUIRED = _enum_auto()
|
||||||
|
|
||||||
|
|
||||||
|
class AffinityTopology(str, _AutoNameEnum):
|
||||||
|
compute = _enum_auto()
|
||||||
|
node = _enum_auto()
|
||||||
|
|
||||||
|
|
||||||
|
class BootDevice(str, _AutoNameEnum):
|
||||||
|
cdrom = _enum_auto()
|
||||||
|
hd = _enum_auto()
|
||||||
|
network = _enum_auto()
|
||||||
|
|
||||||
|
|
||||||
|
class Chipset(str, _AutoNameEnum):
|
||||||
|
Q35 = _enum_auto()
|
||||||
|
i440fx = _enum_auto()
|
||||||
|
|
||||||
|
|
||||||
|
class Driver(str, _AutoNameEnum):
|
||||||
|
KVM_X86 = _enum_auto()
|
||||||
|
SVA_KVM_X86 = _enum_auto()
|
||||||
|
|
||||||
|
|
||||||
|
class NetType(str, _AutoNameEnum):
|
||||||
|
DPDK = _enum_auto()
|
||||||
|
EMPTY = _enum_auto()
|
||||||
|
EXTNET = _enum_auto()
|
||||||
|
VFNIC = _enum_auto()
|
||||||
|
VINS = _enum_auto()
|
||||||
|
|
||||||
|
|
||||||
|
class NumaAffinity(str, _AutoNameEnum):
|
||||||
|
none = _enum_auto()
|
||||||
|
strict = _enum_auto()
|
||||||
|
loose = _enum_auto()
|
||||||
|
|
||||||
|
|
||||||
|
class TXMode(str, _AutoNameEnum):
|
||||||
|
iothread = _enum_auto()
|
||||||
|
selected_by_hypervisor = 'selected by hypervisor'
|
||||||
|
timer = _enum_auto()
|
||||||
|
|
||||||
|
|
||||||
|
class Ioeventfd(str, _AutoNameEnum):
|
||||||
|
off = _enum_auto()
|
||||||
|
on = _enum_auto()
|
||||||
|
selected_by_hypervisor = 'selected by hypervisor'
|
||||||
|
|
||||||
|
|
||||||
|
class EventIdx(str, _AutoNameEnum):
|
||||||
|
off = _enum_auto()
|
||||||
|
on = _enum_auto()
|
||||||
|
selected_by_hypervisor = 'selected by hypervisor'
|
||||||
|
|
||||||
|
|
||||||
|
class ResourceGroupStatus(str, _AutoNameEnum):
|
||||||
|
CREATED = _enum_auto()
|
||||||
|
DELETED = _enum_auto()
|
||||||
|
DESTROYED = _enum_auto()
|
||||||
|
DESTROYING = _enum_auto()
|
||||||
|
DISABLED = _enum_auto()
|
||||||
|
DISABLING = _enum_auto()
|
||||||
|
ENABLED = _enum_auto()
|
||||||
|
ENABLING = _enum_auto()
|
||||||
|
MODELED = _enum_auto()
|
||||||
|
RESTORING = _enum_auto()
|
||||||
|
|
||||||
|
|
||||||
|
class LockStatus(str, _AutoNameEnum):
|
||||||
|
LOCKED = _enum_auto()
|
||||||
|
UNLOCKED = _enum_auto()
|
||||||
|
|
||||||
|
|
||||||
|
class ComputeFeature(str, _AutoNameEnum):
|
||||||
|
cpupin = _enum_auto()
|
||||||
|
dpdk = _enum_auto()
|
||||||
|
hugepages = _enum_auto()
|
||||||
|
numa = _enum_auto()
|
||||||
|
vfnic = _enum_auto()
|
||||||
|
|
||||||
|
|
||||||
|
class RGDefaultNetType(str, _AutoNameEnum):
|
||||||
|
NONE = _enum_auto()
|
||||||
|
PRIVATE = _enum_auto()
|
||||||
|
PUBLIC = _enum_auto()
|
||||||
|
|
||||||
|
|
||||||
|
class RGResourceType(str, _AutoNameEnum):
|
||||||
|
compute = _enum_auto()
|
||||||
|
k8s = _enum_auto()
|
||||||
|
lb = _enum_auto()
|
||||||
|
vins = _enum_auto()
|
||||||
|
|
||||||
|
|
||||||
|
class DiskStatus(str, _AutoNameEnum):
|
||||||
|
ASSIGNED = _enum_auto()
|
||||||
|
CREATED = _enum_auto()
|
||||||
|
DELETED = _enum_auto()
|
||||||
|
DESTROYED = _enum_auto()
|
||||||
|
DESTROYING = _enum_auto()
|
||||||
|
MODELED = _enum_auto()
|
||||||
|
PURGED = _enum_auto()
|
||||||
|
REPLICATION = _enum_auto()
|
||||||
|
|
||||||
|
|
||||||
|
class DiskTechStatus(str, _AutoNameEnum):
|
||||||
|
ALLOCATED = _enum_auto()
|
||||||
|
UNALLOCATED = _enum_auto()
|
||||||
|
|
||||||
|
|
||||||
|
class VMStatus(str, _AutoNameEnum):
|
||||||
|
CREATED = _enum_auto()
|
||||||
|
DELETED = _enum_auto()
|
||||||
|
DELETING = _enum_auto()
|
||||||
|
DESTROYED = _enum_auto()
|
||||||
|
DESTROYING = _enum_auto()
|
||||||
|
DISABLED = _enum_auto()
|
||||||
|
ENABLED = _enum_auto()
|
||||||
|
MODELED = _enum_auto()
|
||||||
|
REDEPLOYING = _enum_auto()
|
||||||
|
|
||||||
|
|
||||||
|
class VMTechStatus(str, _AutoNameEnum):
|
||||||
|
BACKUP_RUNNING = _enum_auto()
|
||||||
|
BACKUP_STOPPED = _enum_auto()
|
||||||
|
DOWN = _enum_auto()
|
||||||
|
MIGRATING = _enum_auto()
|
||||||
|
PAUSED = _enum_auto()
|
||||||
|
PAUSING = _enum_auto()
|
||||||
|
SCHEDULED = _enum_auto()
|
||||||
|
STARTED = _enum_auto()
|
||||||
|
STARTING = _enum_auto()
|
||||||
|
STOPPED = _enum_auto()
|
||||||
|
STOPPING = _enum_auto()
|
||||||
|
|
||||||
|
|
||||||
|
class DiskType(str, _AutoNameEnum):
|
||||||
|
B = _enum_auto()
|
||||||
|
D = _enum_auto()
|
@ -0,0 +1,20 @@
|
|||||||
|
import dynamix_sdk.base as _base
|
||||||
|
from . import enums as _enums
|
||||||
|
|
||||||
|
|
||||||
|
class DiskAPIParamsNM(_base.BaseAPIParamsNestedModel):
|
||||||
|
name: str
|
||||||
|
size: int
|
||||||
|
|
||||||
|
description: None | str = None
|
||||||
|
image_id: None | int = None
|
||||||
|
sep_id: None | int = None
|
||||||
|
sep_pool_name: None | str = None
|
||||||
|
|
||||||
|
|
||||||
|
class InterfaceAPIParamsNM(_base.BaseAPIParamsNestedModel):
|
||||||
|
net_id: int
|
||||||
|
net_type: _enums.NetType
|
||||||
|
|
||||||
|
ip_addr: None | str = None
|
||||||
|
mtu: None | int = None
|
@ -0,0 +1,343 @@
|
|||||||
|
import dynamix_sdk.base as _base
|
||||||
|
from dynamix_sdk.utils import EmptyStr as _EmptyStr
|
||||||
|
from . import enums as _enums
|
||||||
|
|
||||||
|
|
||||||
|
class AccessAPIResultNM(_base.BaseAPIResultNestedModel):
|
||||||
|
explicit: bool
|
||||||
|
guid: str
|
||||||
|
access_type: _enums.AccessType
|
||||||
|
status: str
|
||||||
|
type: str
|
||||||
|
user_group_id: str
|
||||||
|
|
||||||
|
|
||||||
|
class AffinityRuleAPIResultNM(_base.BaseAPIResultNestedModel):
|
||||||
|
guid: str
|
||||||
|
key: str
|
||||||
|
mode: _enums.AffinityMode
|
||||||
|
policy: _enums.AffinityPolicy
|
||||||
|
topology: _enums.AffinityTopology
|
||||||
|
value: str
|
||||||
|
|
||||||
|
|
||||||
|
class QOSAPIResultNM(_base.BaseAPIResultNestedModel):
|
||||||
|
egress_rate: int
|
||||||
|
guid: str
|
||||||
|
ingress_burst: int
|
||||||
|
ingress_rate: int
|
||||||
|
|
||||||
|
|
||||||
|
class VMACLAPIResultNM(_base.BaseAPIResultNestedModel):
|
||||||
|
account: list[AccessAPIResultNM]
|
||||||
|
compute: list[AccessAPIResultNM]
|
||||||
|
rg: list[AccessAPIResultNM]
|
||||||
|
|
||||||
|
|
||||||
|
class LibvirtSettingsAPIResultNM(_base.BaseAPIResultNestedModel):
|
||||||
|
event_idx: _EmptyStr | _enums.EventIdx
|
||||||
|
guid: str
|
||||||
|
ioeventfd: _EmptyStr | _enums.Ioeventfd
|
||||||
|
queues: int
|
||||||
|
rx_queue_size: int
|
||||||
|
tx_mode: _EmptyStr | _enums.TXMode
|
||||||
|
tx_queue_size: int
|
||||||
|
|
||||||
|
|
||||||
|
class BaseInterfaceAPIResultNM(_base.BaseAPIResultNestedModel):
|
||||||
|
bus_number: int
|
||||||
|
conn_id: int
|
||||||
|
conn_type: str
|
||||||
|
default_gw: str
|
||||||
|
enabled: bool
|
||||||
|
flip_group_id: int
|
||||||
|
guid: str
|
||||||
|
ip_addr: str
|
||||||
|
libvirt_settings: LibvirtSettingsAPIResultNM
|
||||||
|
listen_ssh: bool
|
||||||
|
mac: str
|
||||||
|
mtu: int
|
||||||
|
name: str
|
||||||
|
net_id: int
|
||||||
|
net_mask: int
|
||||||
|
net_type: _enums.NetType
|
||||||
|
node_id: int
|
||||||
|
pci_slot: int
|
||||||
|
target: str
|
||||||
|
type: str
|
||||||
|
vnf_ids: list[int]
|
||||||
|
|
||||||
|
|
||||||
|
class InterfaceAPIResultNM(BaseInterfaceAPIResultNM):
|
||||||
|
qos: QOSAPIResultNM
|
||||||
|
|
||||||
|
|
||||||
|
class OSUserAPIResultNM(_base.BaseAPIResultNestedModel):
|
||||||
|
login: str
|
||||||
|
password: str
|
||||||
|
pub_key: str
|
||||||
|
guid: str
|
||||||
|
|
||||||
|
|
||||||
|
class SnapshotSetAPIResultNM(_base.BaseAPIResultNestedModel):
|
||||||
|
disks: list[int]
|
||||||
|
guid: str
|
||||||
|
label: str
|
||||||
|
timestamp: int
|
||||||
|
|
||||||
|
@property
|
||||||
|
def datetime(self):
|
||||||
|
return self._get_datetime_from_timestamp(self.timestamp)
|
||||||
|
|
||||||
|
|
||||||
|
class IOTuneAPIResultNM(_base.BaseAPIResultNestedModel):
|
||||||
|
read_bytes_sec: None | int = None
|
||||||
|
read_bytes_sec_max: None | int = None
|
||||||
|
read_iops_sec: None | int = None
|
||||||
|
read_iops_sec_max: None | int = None
|
||||||
|
size_iops_sec: None | int = None
|
||||||
|
total_bytes_sec: None | int = None
|
||||||
|
total_bytes_sec_max: None | int = None
|
||||||
|
total_iops_sec: None | int = None
|
||||||
|
total_iops_sec_max: None | int = None
|
||||||
|
write_bytes_sec: None | int = None
|
||||||
|
write_bytes_sec_max: None | int = None
|
||||||
|
write_iops_sec: None | int = None
|
||||||
|
write_iops_sec_max: None | int = None
|
||||||
|
|
||||||
|
|
||||||
|
class SnapshotAPIResultNM(_base.BaseAPIResultNestedModel):
|
||||||
|
guid: str
|
||||||
|
label: str
|
||||||
|
reference_id: str
|
||||||
|
res_id: str
|
||||||
|
snapshot_set_guid: str
|
||||||
|
snapshot_set_timestamp: int
|
||||||
|
timestamp: int
|
||||||
|
|
||||||
|
@property
|
||||||
|
def datetime(self):
|
||||||
|
return self._get_datetime_from_timestamp(self.timestamp)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def snapshot_set_datetime(self):
|
||||||
|
return self._get_datetime_from_timestamp(self.snapshot_set_timestamp)
|
||||||
|
|
||||||
|
|
||||||
|
class ReplicationAPIResultNM(_base.BaseAPIResultNestedModel):
|
||||||
|
disk_id: int
|
||||||
|
pool_id: str
|
||||||
|
role: str
|
||||||
|
self_volume_id: str
|
||||||
|
storage_id: str
|
||||||
|
volume_id: str
|
||||||
|
|
||||||
|
|
||||||
|
class BaseDiskAPIResultNM(_base.BaseAPIResultNestedModel):
|
||||||
|
bus_number: int
|
||||||
|
id: int
|
||||||
|
pci_slot: int
|
||||||
|
|
||||||
|
|
||||||
|
class DiskAPIResultNM(BaseDiskAPIResultNM):
|
||||||
|
account_id: int
|
||||||
|
acl: dict
|
||||||
|
boot_partition: int
|
||||||
|
created_timestamp: int
|
||||||
|
deleted_timestamp: int
|
||||||
|
description: str
|
||||||
|
destruction_timestamp: int
|
||||||
|
disk_path: str
|
||||||
|
grid_id: int
|
||||||
|
guid: int
|
||||||
|
image_id: int
|
||||||
|
images: list
|
||||||
|
io_tune: IOTuneAPIResultNM
|
||||||
|
iqn: str
|
||||||
|
login: str
|
||||||
|
milestones: int
|
||||||
|
name: str
|
||||||
|
order: int
|
||||||
|
params: str
|
||||||
|
parent_id: int
|
||||||
|
password: str
|
||||||
|
present_to: list[int]
|
||||||
|
purge_timestamp: int
|
||||||
|
reality_device_number: int
|
||||||
|
replication_dict: dict
|
||||||
|
res_id: str
|
||||||
|
role: str
|
||||||
|
sep_id: int
|
||||||
|
sep_pool_name: str
|
||||||
|
shareable: bool
|
||||||
|
size_max: int
|
||||||
|
size_used: float
|
||||||
|
snapshots: list[SnapshotAPIResultNM]
|
||||||
|
status: _enums.DiskStatus
|
||||||
|
tech_status: _enums.DiskTechStatus
|
||||||
|
type: _enums.DiskType
|
||||||
|
|
||||||
|
updated_timestamp: int = 0
|
||||||
|
|
||||||
|
@property
|
||||||
|
def created_datetime(self):
|
||||||
|
return self._get_datetime_from_timestamp(self.created_timestamp)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def deleted_datetime(self):
|
||||||
|
return self._get_datetime_from_timestamp(self.deleted_timestamp)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def destruction_datetime(self):
|
||||||
|
return self._get_datetime_from_timestamp(self.destruction_timestamp)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def updated_datetime(self):
|
||||||
|
return self._get_datetime_from_timestamp(self.updated_timestamp)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def purge_datetime(self):
|
||||||
|
return self._get_datetime_from_timestamp(self.purge_timestamp)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def replication(self):
|
||||||
|
if self.replication_dict:
|
||||||
|
return ReplicationAPIResultNM(**self.replication_dict)
|
||||||
|
|
||||||
|
|
||||||
|
class TenantQuotasAPIResultNM(_base.BaseAPIResultNestedModel):
|
||||||
|
cpu: int
|
||||||
|
disk_size: int
|
||||||
|
ext_traffic: int
|
||||||
|
gpu: int
|
||||||
|
public_ip: int
|
||||||
|
ram: float | int
|
||||||
|
storage: int
|
||||||
|
|
||||||
|
|
||||||
|
class ResourceGroupAPIResultNM(_base.BaseAPIResultNestedModel):
|
||||||
|
account_id: int
|
||||||
|
account_name: str
|
||||||
|
acl: list[AccessAPIResultNM]
|
||||||
|
compute_features: list[_enums.ComputeFeature]
|
||||||
|
cpu_allocation_parameter: str
|
||||||
|
cpu_allocation_ratio: int
|
||||||
|
created_by: str
|
||||||
|
created_timestamp: int
|
||||||
|
default_net_id: int
|
||||||
|
default_net_type: _enums.RGDefaultNetType
|
||||||
|
deleted_by: str
|
||||||
|
deleted_timestamp: int
|
||||||
|
description: str
|
||||||
|
grid_id: int
|
||||||
|
guid: int
|
||||||
|
id: int
|
||||||
|
lock_status: _enums.LockStatus
|
||||||
|
milestones: int
|
||||||
|
name: str
|
||||||
|
quotas: TenantQuotasAPIResultNM
|
||||||
|
register_computes: bool
|
||||||
|
resource_types: list[_enums.RGResourceType]
|
||||||
|
secret: str
|
||||||
|
status: _enums.ResourceGroupStatus
|
||||||
|
uniq_pools: list[str]
|
||||||
|
updated_by: str
|
||||||
|
updated_timestamp: int
|
||||||
|
vins_ids: list[int]
|
||||||
|
vm_ids: list[int]
|
||||||
|
|
||||||
|
dirty: bool | None = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def created_datetime(self):
|
||||||
|
return self._get_datetime_from_timestamp(self.created_timestamp)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def deleted_datetime(self):
|
||||||
|
return self._get_datetime_from_timestamp(self.deleted_timestamp)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def updated_datetime(self):
|
||||||
|
return self._get_datetime_from_timestamp(self.updated_timestamp)
|
||||||
|
|
||||||
|
|
||||||
|
class BaseVMAPIResultNM(_base.BaseAPIResultNestedModel):
|
||||||
|
account_id: int
|
||||||
|
account_name: str
|
||||||
|
affinity_label: str
|
||||||
|
affinity_rules: list[AffinityRuleAPIResultNM]
|
||||||
|
affinity_weight: int
|
||||||
|
anti_affinity_rules: list[AffinityRuleAPIResultNM]
|
||||||
|
arch: str
|
||||||
|
auto_start: bool
|
||||||
|
boot_disk_size: int
|
||||||
|
boot_order: list[_enums.BootDevice]
|
||||||
|
cd_image_id: int
|
||||||
|
chipset: _enums.Chipset
|
||||||
|
clone_ids: list[int]
|
||||||
|
clone_reference: int
|
||||||
|
compute_ci_id: int
|
||||||
|
cpu: int
|
||||||
|
cpu_pin: bool
|
||||||
|
created_by: str
|
||||||
|
created_timestamp: int
|
||||||
|
custom_fields: dict
|
||||||
|
deleted_by: str
|
||||||
|
deleted_timestamp: int
|
||||||
|
description: str
|
||||||
|
devices: dict
|
||||||
|
driver: _enums.Driver
|
||||||
|
gpu_ids: list[int]
|
||||||
|
grid_id: int
|
||||||
|
guid: int
|
||||||
|
hp_backed: bool
|
||||||
|
id: int
|
||||||
|
image_id: int
|
||||||
|
lock_status: _enums.LockStatus
|
||||||
|
manager_id: int
|
||||||
|
manager_type: str
|
||||||
|
migration_job: int
|
||||||
|
milestones: int
|
||||||
|
name: str
|
||||||
|
need_reboot: bool
|
||||||
|
numa_affinity: _enums.NumaAffinity
|
||||||
|
numa_node_id: int
|
||||||
|
pinned: bool
|
||||||
|
preferred_cpu_cores: list[int]
|
||||||
|
ram: int
|
||||||
|
reference_id: str
|
||||||
|
registered: bool
|
||||||
|
res_name: str
|
||||||
|
reserved_cpu_cores: list[int]
|
||||||
|
rg_id: int
|
||||||
|
rg_name: str
|
||||||
|
snapshot_sets: list[SnapshotSetAPIResultNM]
|
||||||
|
stateless_sep_id: int
|
||||||
|
stateless_sep_type: str
|
||||||
|
status: _enums.VMStatus
|
||||||
|
tags: dict
|
||||||
|
tech_status: _enums.VMTechStatus
|
||||||
|
updated_by: str
|
||||||
|
updated_timestamp: int
|
||||||
|
user_managed: bool
|
||||||
|
virtual_image_id: int
|
||||||
|
|
||||||
|
@property
|
||||||
|
def created_datetime(self):
|
||||||
|
return self._get_datetime_from_timestamp(self.created_timestamp)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def deleted_datetime(self):
|
||||||
|
return self._get_datetime_from_timestamp(self.deleted_timestamp)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def updated_datetime(self):
|
||||||
|
return self._get_datetime_from_timestamp(self.updated_timestamp)
|
||||||
|
|
||||||
|
|
||||||
|
class VMAPIResultNM(BaseVMAPIResultNM):
|
||||||
|
acl: list # BDX-7995
|
||||||
|
disks: list[BaseDiskAPIResultNM]
|
||||||
|
interfaces: list[BaseInterfaceAPIResultNM]
|
||||||
|
total_disks_size: int
|
||||||
|
vins_count: int
|
@ -0,0 +1 @@
|
|||||||
|
from ._api import *
|
@ -0,0 +1,14 @@
|
|||||||
|
import dynamix_sdk.base as _base
|
||||||
|
from .account import *
|
||||||
|
from .compute import *
|
||||||
|
from .kvmx86 import *
|
||||||
|
from .rg import *
|
||||||
|
from .user import *
|
||||||
|
|
||||||
|
|
||||||
|
class CloudapiAPI(_base.BaseAPI):
|
||||||
|
account: CloudapiAccountAPI
|
||||||
|
compute: CloudapiComputeAPI
|
||||||
|
kvmx86: CloudapiKvmx86API
|
||||||
|
rg: CloudapiRgAPI
|
||||||
|
user: CloudapiUserAPI
|
@ -0,0 +1 @@
|
|||||||
|
from ._api import *
|
@ -0,0 +1,17 @@
|
|||||||
|
import dynamix_sdk.base as _base
|
||||||
|
from .add_user import *
|
||||||
|
from .delete_user import *
|
||||||
|
from .disable import *
|
||||||
|
from .enable import *
|
||||||
|
from .update_user import *
|
||||||
|
|
||||||
|
|
||||||
|
class CloudapiAccountAPI(
|
||||||
|
_base.BaseAPI,
|
||||||
|
CloudapiAccountAddUserProtocol,
|
||||||
|
CloudapiAccountDeleteUserProtocol,
|
||||||
|
CloudapiAccountDisableProtocol,
|
||||||
|
CloudapiAccountEnableProtocol,
|
||||||
|
CloudapiAccountUpdateUserProtocol,
|
||||||
|
):
|
||||||
|
pass
|
@ -0,0 +1,17 @@
|
|||||||
|
import dynamix_sdk.base as _base
|
||||||
|
import dynamix_sdk.api._nested as _nested
|
||||||
|
|
||||||
|
|
||||||
|
class CloudapiAccountAddUserResultBool(_base.BaseAPIResultBool):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class CloudapiAccountAddUserProtocol(_base.BasePostAPIFunctionProtocol):
|
||||||
|
def add_user(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
account_id: int,
|
||||||
|
access_type: _nested.AccessType,
|
||||||
|
user_id: str,
|
||||||
|
) -> CloudapiAccountAddUserResultBool:
|
||||||
|
...
|
@ -0,0 +1,15 @@
|
|||||||
|
import dynamix_sdk.base as _base
|
||||||
|
|
||||||
|
|
||||||
|
class CloudapiAccountDeleteUserResultBool(_base.BaseAPIResultBool):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class CloudapiAccountDeleteUserProtocol(_base.BasePostAPIFunctionProtocol):
|
||||||
|
def delete_user(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
account_id: int,
|
||||||
|
user_id: str,
|
||||||
|
) -> CloudapiAccountDeleteUserResultBool:
|
||||||
|
...
|
@ -0,0 +1,14 @@
|
|||||||
|
import dynamix_sdk.base as _base
|
||||||
|
|
||||||
|
|
||||||
|
class CloudapiAccountDisableResultBool(_base.BaseAPIResultBool):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class CloudapiAccountDisableProtocol(_base.BasePostAPIFunctionProtocol):
|
||||||
|
def disable(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
account_id: int,
|
||||||
|
) -> CloudapiAccountDisableResultBool:
|
||||||
|
...
|
@ -0,0 +1,14 @@
|
|||||||
|
import dynamix_sdk.base as _base
|
||||||
|
|
||||||
|
|
||||||
|
class CloudapiAccountEnableResultBool(_base.BaseAPIResultBool):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class CloudapiAccountEnableProtocol(_base.BasePostAPIFunctionProtocol):
|
||||||
|
def enable(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
account_id: int,
|
||||||
|
) -> CloudapiAccountEnableResultBool:
|
||||||
|
...
|
@ -0,0 +1,17 @@
|
|||||||
|
import dynamix_sdk.base as _base
|
||||||
|
import dynamix_sdk.api._nested as _nested
|
||||||
|
|
||||||
|
|
||||||
|
class CloudapiAccountUpdateUserResultBool(_base.BaseAPIResultBool):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class CloudapiAccountUpdateUserProtocol(_base.BasePostAPIFunctionProtocol):
|
||||||
|
def update_user(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
account_id: int,
|
||||||
|
access_type: _nested.AccessType,
|
||||||
|
user_id: str,
|
||||||
|
) -> CloudapiAccountUpdateUserResultBool:
|
||||||
|
...
|
@ -0,0 +1 @@
|
|||||||
|
from ._api import *
|
@ -0,0 +1,15 @@
|
|||||||
|
import dynamix_sdk.base as _base
|
||||||
|
from .delete import *
|
||||||
|
from .get import *
|
||||||
|
from .list import *
|
||||||
|
from .update import *
|
||||||
|
|
||||||
|
|
||||||
|
class CloudapiComputeAPI(
|
||||||
|
_base.BaseAPI,
|
||||||
|
CloudapiComputeDeleteProtocol,
|
||||||
|
CloudapiComputeGetProtocol,
|
||||||
|
CloudapiComputeListProtocol,
|
||||||
|
CloudapiComputeUpdateProtocol,
|
||||||
|
):
|
||||||
|
pass
|
@ -0,0 +1,17 @@
|
|||||||
|
import dynamix_sdk.base as _base
|
||||||
|
|
||||||
|
|
||||||
|
class CloudapiComputeDeleteResultBool(_base.BaseAPIResultBool):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class CloudapiComputeDeleteProtocol(_base.BasePostAPIFunctionProtocol):
|
||||||
|
def delete(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
compute_id: int,
|
||||||
|
|
||||||
|
detach_disks: bool = False,
|
||||||
|
permanently: bool = False,
|
||||||
|
) -> CloudapiComputeDeleteResultBool:
|
||||||
|
...
|
@ -0,0 +1,31 @@
|
|||||||
|
import dynamix_sdk.base as _base
|
||||||
|
import dynamix_sdk.api._nested as _nested
|
||||||
|
|
||||||
|
|
||||||
|
class CloudapiComputeGetResultModel(
|
||||||
|
_base.BaseAPIResultModel,
|
||||||
|
_nested.BaseVMAPIResultNM,
|
||||||
|
):
|
||||||
|
acl: _nested.VMACLAPIResultNM
|
||||||
|
ci_user_data: dict
|
||||||
|
disks: list[_nested.DiskAPIResultNM]
|
||||||
|
image_name: None | str
|
||||||
|
interfaces: list[_nested.InterfaceAPIResultNM]
|
||||||
|
os_users: list[_nested.OSUserAPIResultNM]
|
||||||
|
virtual_image_name: None | str
|
||||||
|
vns_password: str
|
||||||
|
|
||||||
|
natable_vins_id: int = 0
|
||||||
|
natable_vins_ip: str = ''
|
||||||
|
natable_vins_name: str = ''
|
||||||
|
natable_vins_network: str = ''
|
||||||
|
natable_vins_network_name: str = ''
|
||||||
|
|
||||||
|
|
||||||
|
class CloudapiComputeGetProtocol(_base.BasePostAPIFunctionProtocol):
|
||||||
|
def get(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
compute_id: int,
|
||||||
|
) -> CloudapiComputeGetResultModel:
|
||||||
|
...
|
@ -0,0 +1,29 @@
|
|||||||
|
import dynamix_sdk.base as _base
|
||||||
|
import dynamix_sdk.api._nested as _nested
|
||||||
|
|
||||||
|
|
||||||
|
class CloudapiComputeListResultModel(_base.BaseAPIResultModel):
|
||||||
|
data: list[_nested.VMAPIResultNM]
|
||||||
|
entry_count: int
|
||||||
|
|
||||||
|
|
||||||
|
class CloudapiComputeListProtocol(_base.BasePostAPIFunctionProtocol):
|
||||||
|
def list(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
account_id: int | None = None,
|
||||||
|
ext_net_id: int | None = None,
|
||||||
|
ext_net_name: str | None = None,
|
||||||
|
id: int | None = None,
|
||||||
|
include_deleted: bool = False,
|
||||||
|
ip_addr: str | None = None,
|
||||||
|
name: str | None = None,
|
||||||
|
page_number: int | None = None,
|
||||||
|
page_size: int | None = None,
|
||||||
|
rg_id: int | None = None,
|
||||||
|
rg_name: str | None = None,
|
||||||
|
sort_by: str | None = None,
|
||||||
|
status: _nested.VMStatus | None = None,
|
||||||
|
tech_status: _nested.VMTechStatus | None = None,
|
||||||
|
) -> CloudapiComputeListResultModel:
|
||||||
|
...
|
@ -0,0 +1,23 @@
|
|||||||
|
import dynamix_sdk.base as _base
|
||||||
|
import dynamix_sdk.api._nested as _nested
|
||||||
|
|
||||||
|
|
||||||
|
class CloudapiComputeUpdateResultBool(_base.BaseAPIResultBool):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class CloudapiComputeUpdateProtocol(_base.BasePostAPIFunctionProtocol):
|
||||||
|
def update(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
compute_id: int,
|
||||||
|
auto_start: None | bool = None,
|
||||||
|
chipset: None | _nested.Chipset = None,
|
||||||
|
cpu_pin: None | bool = None,
|
||||||
|
description: None | str = None,
|
||||||
|
hp_backed: None | bool = None,
|
||||||
|
name: None | str = None,
|
||||||
|
numa_affinity: None | _nested.NumaAffinity = None,
|
||||||
|
preferred_cpu_cores: None | list[int] = None,
|
||||||
|
) -> CloudapiComputeUpdateResultBool:
|
||||||
|
...
|
@ -0,0 +1 @@
|
|||||||
|
from ._api import *
|
@ -0,0 +1,9 @@
|
|||||||
|
import dynamix_sdk.base as _base
|
||||||
|
from .create import *
|
||||||
|
|
||||||
|
|
||||||
|
class CloudapiKvmx86API(
|
||||||
|
_base.BaseAPI,
|
||||||
|
CloudapiKvmx86CreateProtocol,
|
||||||
|
):
|
||||||
|
pass
|
@ -0,0 +1,37 @@
|
|||||||
|
import dynamix_sdk.base as _base
|
||||||
|
import dynamix_sdk.api._nested as _nested
|
||||||
|
|
||||||
|
|
||||||
|
class CloudapiKvmx86CreateResultInt(_base.BaseAPIResultInt):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class CloudapiKvmx86CreateProtocol(_base.BasePostAPIFunctionProtocol):
|
||||||
|
def create(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
cpu: int,
|
||||||
|
name: str,
|
||||||
|
ram: int,
|
||||||
|
rg_id: int,
|
||||||
|
boot_disk_size: None | int = None,
|
||||||
|
chipset: _nested.Chipset = _nested.Chipset.i440fx,
|
||||||
|
ci_user_data: None | dict = None,
|
||||||
|
cpu_pin: bool = False,
|
||||||
|
custom_fields: None | str = None,
|
||||||
|
data_disks: None | list[_nested.DiskAPIParamsNM] = None,
|
||||||
|
description: None | str = None,
|
||||||
|
driver: _nested.Driver = _nested.Driver.KVM_X86,
|
||||||
|
hp_backed: bool = False,
|
||||||
|
image_id: None | int = None,
|
||||||
|
interfaces: None | list[_nested.InterfaceAPIParamsNM] = None,
|
||||||
|
ipa_type: None | str = None,
|
||||||
|
numa_affinity: _nested.NumaAffinity = _nested.NumaAffinity.none,
|
||||||
|
preferred_cpu_cores: None | list[int] = None,
|
||||||
|
sep_id: None | int = None,
|
||||||
|
sep_pool_name: None | str = None,
|
||||||
|
start: bool = True,
|
||||||
|
system_name: None | str = None,
|
||||||
|
without_boot_disk: bool = False,
|
||||||
|
) -> CloudapiKvmx86CreateResultInt:
|
||||||
|
...
|
@ -0,0 +1 @@
|
|||||||
|
from ._api import *
|
@ -0,0 +1,13 @@
|
|||||||
|
import dynamix_sdk.base as _base
|
||||||
|
from .create import *
|
||||||
|
from .get import *
|
||||||
|
from .list import *
|
||||||
|
|
||||||
|
|
||||||
|
class CloudapiRgAPI(
|
||||||
|
_base.BaseAPI,
|
||||||
|
CloudapiRgCreateProtocol,
|
||||||
|
CloudapiRgGetProtocol,
|
||||||
|
CloudapiRgListProtocol,
|
||||||
|
):
|
||||||
|
pass
|
@ -0,0 +1,31 @@
|
|||||||
|
import dynamix_sdk.base as _base
|
||||||
|
import dynamix_sdk.api._nested as _nested
|
||||||
|
|
||||||
|
|
||||||
|
class CloudapiRgCreateResultBoolInt(_base.BaseAPIResultInt):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class CloudapiRgCreateProtocol(_base.BasePostAPIFunctionProtocol):
|
||||||
|
def create(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
account_id: int,
|
||||||
|
grid_id: int,
|
||||||
|
name: str,
|
||||||
|
cpu_quota: int = -1,
|
||||||
|
default_net_type: _nested.RGDefaultNetType = (
|
||||||
|
_nested.RGDefaultNetType.PRIVATE
|
||||||
|
),
|
||||||
|
description: str | None = None,
|
||||||
|
ext_net_id: int = 0,
|
||||||
|
ext_net_ip: str | None = None,
|
||||||
|
ext_traffic_quota: int = -1,
|
||||||
|
ip_cidr: str | None = None,
|
||||||
|
owner: str | None = None,
|
||||||
|
public_ip_quota: int = -1,
|
||||||
|
ram_quota: int = -1,
|
||||||
|
register_computes: bool = False,
|
||||||
|
storage_quota: int = -1,
|
||||||
|
) -> CloudapiRgCreateResultBoolInt:
|
||||||
|
...
|
@ -0,0 +1,18 @@
|
|||||||
|
import dynamix_sdk.base as _base
|
||||||
|
import dynamix_sdk.api._nested as _nested
|
||||||
|
|
||||||
|
|
||||||
|
class CloudapiRgGetResultModel(
|
||||||
|
_base.BaseAPIResultModel,
|
||||||
|
_nested.ResourceGroupAPIResultNM,
|
||||||
|
):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class CloudapiRgGetProtocol(_base.BasePostAPIFunctionProtocol):
|
||||||
|
def get(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
rg_id: int,
|
||||||
|
) -> CloudapiRgGetResultModel:
|
||||||
|
...
|
@ -0,0 +1,27 @@
|
|||||||
|
import dynamix_sdk.base as _base
|
||||||
|
import dynamix_sdk.api._nested as _nested
|
||||||
|
|
||||||
|
|
||||||
|
class CloudapiRgListResultModel(_base.BaseAPIResultModel):
|
||||||
|
data: list[_nested.ResourceGroupAPIResultNM]
|
||||||
|
entry_count: int
|
||||||
|
|
||||||
|
|
||||||
|
class CloudapiRgListProtocol(_base.BasePostAPIFunctionProtocol):
|
||||||
|
def list(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
account_id: int | None = None,
|
||||||
|
account_name: str | None = None,
|
||||||
|
created_after_timestamp: int | None = None,
|
||||||
|
created_before_timestamp: int | None = None,
|
||||||
|
id: int | None = None,
|
||||||
|
include_deleted: bool = False,
|
||||||
|
lock_status: _nested.LockStatus | None = None,
|
||||||
|
name: str | None = None,
|
||||||
|
page_number: int | None = None,
|
||||||
|
page_size: int | None = None,
|
||||||
|
sort_by: str | None = None,
|
||||||
|
status: _nested.ResourceGroupStatus | None = None,
|
||||||
|
) -> CloudapiRgListResultModel:
|
||||||
|
...
|
@ -0,0 +1 @@
|
|||||||
|
from ._api import *
|
@ -0,0 +1,9 @@
|
|||||||
|
import dynamix_sdk.base as _base
|
||||||
|
from .get import *
|
||||||
|
|
||||||
|
|
||||||
|
class CloudapiUserAPI(
|
||||||
|
_base.BaseAPI,
|
||||||
|
CloudapiUserGetProtocol,
|
||||||
|
):
|
||||||
|
pass
|
@ -0,0 +1,12 @@
|
|||||||
|
import dynamix_sdk.base as _base
|
||||||
|
|
||||||
|
|
||||||
|
class CloudapiUserGetResultModel(_base.BaseAPIResultModel):
|
||||||
|
data: dict
|
||||||
|
email_addresses: list[str]
|
||||||
|
user_name: str
|
||||||
|
|
||||||
|
|
||||||
|
class CloudapiUserGetProtocol(_base.BasePostAPIFunctionProtocol):
|
||||||
|
def get(self, *, user_name: str) -> CloudapiUserGetResultModel:
|
||||||
|
...
|
@ -0,0 +1,224 @@
|
|||||||
|
# sdk_name[__model_class_name]: dynamix_name
|
||||||
|
access_type: accesstype
|
||||||
|
access_type__AccessAPIResultNM: right
|
||||||
|
account: accountAcl
|
||||||
|
account_id: accountId
|
||||||
|
account_name: accountName
|
||||||
|
acl: acl
|
||||||
|
acl__CloudapiComputeGetResultModel: ACL
|
||||||
|
admin: admin
|
||||||
|
affinity_label: affinityLabel
|
||||||
|
affinity_rules: affinityRules
|
||||||
|
affinity_weight: affinityWeight
|
||||||
|
anti_affinity_rules: antiAffinityRules
|
||||||
|
arch: arch
|
||||||
|
auto_start: autoStart
|
||||||
|
boot_disk_size: bootdiskSize
|
||||||
|
boot_disk_size__CloudapiKvmx86CreateParamsModel: bootDisk
|
||||||
|
boot_order: bootOrder
|
||||||
|
boot_partition: bootPartition
|
||||||
|
bus_number: bus_number
|
||||||
|
cd_image_id: cdImageId
|
||||||
|
chipset: chipset
|
||||||
|
ci_user_data: userdata
|
||||||
|
clone_ids: clones
|
||||||
|
clone_reference: cloneReference
|
||||||
|
compute: computeAcl
|
||||||
|
compute_ci_id: computeciId
|
||||||
|
compute_features: computeFeatures
|
||||||
|
compute_id: computeId
|
||||||
|
conn_id: connId
|
||||||
|
conn_type: connType
|
||||||
|
cpu: cpu
|
||||||
|
cpu__CloudapiComputeGetResultModel: cpus
|
||||||
|
cpu__TenantQuotasAPIResultNM: CU_C
|
||||||
|
cpu__VMAPIResultNM: cpus
|
||||||
|
cpu_allocation_parameter: cpu_allocation_parameter
|
||||||
|
cpu_allocation_ratio: cpu_allocation_ratio
|
||||||
|
cpu_pin: cpupin
|
||||||
|
cpu_quota: maxCPUCapacity
|
||||||
|
created_after_timestamp: createdAfter
|
||||||
|
created_before_timestamp: createdBefore
|
||||||
|
created_by: createdBy
|
||||||
|
created_timestamp: createdTime
|
||||||
|
custom_fields: customFields
|
||||||
|
data: data
|
||||||
|
data_disks: dataDisks
|
||||||
|
default_gw: defGw
|
||||||
|
default_net_id: def_net_id
|
||||||
|
default_net_type: def_net_type
|
||||||
|
default_net_type__CloudapiRgCreateParamsModel: def_net
|
||||||
|
deleted_by: deletedBy
|
||||||
|
deleted_timestamp: deletedTime
|
||||||
|
description: desc
|
||||||
|
destruction_timestamp: destructionTime
|
||||||
|
detach_disks: detachDisks
|
||||||
|
devices: devices
|
||||||
|
dirty: dirty
|
||||||
|
disk_id: diskId
|
||||||
|
disk_path: diskPath
|
||||||
|
disk_size: CU_D
|
||||||
|
disks: disks
|
||||||
|
driver: driver
|
||||||
|
egress_rate: eRate
|
||||||
|
email_addresses: emailaddresses
|
||||||
|
enabled: enabled
|
||||||
|
entry_count: entryCount
|
||||||
|
event_idx: event_idx
|
||||||
|
explicit: explicit
|
||||||
|
ext_net_id: extNetId
|
||||||
|
ext_net_ip: extIp
|
||||||
|
ext_net_name: extNetName
|
||||||
|
ext_traffic: CU_NP
|
||||||
|
ext_traffic_quota: maxNetworkPeerTransfer
|
||||||
|
flip_group_id: flipgroupId
|
||||||
|
gpu: gpu_units
|
||||||
|
gpu_ids: vgpus
|
||||||
|
grid_id: gid
|
||||||
|
guid: guid
|
||||||
|
hp_backed: hpBacked
|
||||||
|
id: id
|
||||||
|
id__CloudapiComputeListParamsModel: by_id
|
||||||
|
id__CloudapiRgListParamsModel: by_id
|
||||||
|
image_id: imageId
|
||||||
|
image_name: imageName
|
||||||
|
images: images
|
||||||
|
include_deleted: includedeleted
|
||||||
|
ingress_burst: inBurst
|
||||||
|
ingress_rate: inRate
|
||||||
|
interfaces: interfaces
|
||||||
|
io_tune: iotune
|
||||||
|
ioeventfd: ioeventfd
|
||||||
|
ip_addr: ipAddress
|
||||||
|
ip_addr__InterfaceAPIParamsNM: ipAddr
|
||||||
|
ip_cidr: ipcidr
|
||||||
|
ipa_type: ipaType
|
||||||
|
iqn: iqn
|
||||||
|
key: key
|
||||||
|
label: label
|
||||||
|
libvirt_settings: libvirtSettings
|
||||||
|
listen_ssh: listenSsh
|
||||||
|
lock_status: lockStatus
|
||||||
|
login: login
|
||||||
|
mac: mac
|
||||||
|
manager_id: managerId
|
||||||
|
manager_type: managerType
|
||||||
|
migration_job: migrationjob
|
||||||
|
milestones: milestones
|
||||||
|
mode: mode
|
||||||
|
mtu: mtu
|
||||||
|
name: name
|
||||||
|
name__DiskAPIParamsNM: diskName
|
||||||
|
natable_vins_id: natableVinsId
|
||||||
|
natable_vins_ip: natableVinsIp
|
||||||
|
natable_vins_name: natableVinsName
|
||||||
|
natable_vins_network: natableVinsNetwork
|
||||||
|
natable_vins_network_name: natableVinsNetworkName
|
||||||
|
need_reboot: needReboot
|
||||||
|
net_id: netId
|
||||||
|
net_mask: netMask
|
||||||
|
net_type: netType
|
||||||
|
node_id: nodeId
|
||||||
|
numa_affinity: numaAffinity
|
||||||
|
numa_node_id: numaNodeId
|
||||||
|
order: order
|
||||||
|
os_users: osUsers
|
||||||
|
owner: owner
|
||||||
|
page_number: page
|
||||||
|
page_size: size
|
||||||
|
params: params
|
||||||
|
parent_id: parentId
|
||||||
|
password: password
|
||||||
|
password__DiskAPIResultNM: passwd
|
||||||
|
pci_slot: pciSlot
|
||||||
|
permanently: permanently
|
||||||
|
pinned: pinned
|
||||||
|
policy: policy
|
||||||
|
pool_id: poolId
|
||||||
|
preferred_cpu_cores: preferredCpu
|
||||||
|
present_to: presentTo
|
||||||
|
pub_key: pubkey
|
||||||
|
public_ip: CU_I
|
||||||
|
public_ip_quota: maxNumPublicIP
|
||||||
|
purge_timestamp: purgeTime
|
||||||
|
qos: qos
|
||||||
|
queues: queues
|
||||||
|
quotas: resourceLimits
|
||||||
|
ram: ram
|
||||||
|
ram__TenantQuotasAPIResultNM: CU_M
|
||||||
|
ram_quota: maxMemoryCapacity
|
||||||
|
read_bytes_sec: read_bytes_sec
|
||||||
|
read_bytes_sec_max: read_bytes_sec_max
|
||||||
|
read_iops_sec: read_iops_sec
|
||||||
|
read_iops_sec_max: read_iops_sec_max
|
||||||
|
reality_device_number: realityDeviceNumber
|
||||||
|
reference_id: referenceId
|
||||||
|
register_computes: registerComputes
|
||||||
|
registered: registered
|
||||||
|
replication_dict: replication
|
||||||
|
res_id: resId
|
||||||
|
res_name: resName
|
||||||
|
reserved_cpu_cores: reservedNodeCpus
|
||||||
|
resource_types: resourceTypes
|
||||||
|
rg: rgAcl
|
||||||
|
rg_id: rgId
|
||||||
|
rg_name: rgName
|
||||||
|
role: role
|
||||||
|
roles: roles
|
||||||
|
rx_queue_size: rx_queue_size
|
||||||
|
secret: secret
|
||||||
|
self_volume_id: selfVolumeId
|
||||||
|
sep_id: sepId
|
||||||
|
sep_pool_name: pool
|
||||||
|
shareable: shareable
|
||||||
|
size__DiskAPIParamsNM: size
|
||||||
|
size_iops_sec: size_iops_sec
|
||||||
|
size_max: sizeMax
|
||||||
|
size_used: sizeUsed
|
||||||
|
snapshot_set_guid: snapSetGuid
|
||||||
|
snapshot_set_timestamp: snapSetTime
|
||||||
|
snapshot_sets: snapSets
|
||||||
|
snapshots: snapshots
|
||||||
|
sort_by: sortBy
|
||||||
|
start: start
|
||||||
|
stateless_sep_id: statelessSepId
|
||||||
|
stateless_sep_type: statelessSepType
|
||||||
|
status: status
|
||||||
|
storage: CU_DM
|
||||||
|
storage_id: storageId
|
||||||
|
storage_quota: maxVDiskCapacity
|
||||||
|
system_name: IS
|
||||||
|
tags: tags
|
||||||
|
target: target
|
||||||
|
tech_status: techStatus
|
||||||
|
timestamp: timestamp
|
||||||
|
topology: topology
|
||||||
|
total_bytes_sec: total_bytes_sec
|
||||||
|
total_bytes_sec_max: total_bytes_sec_max
|
||||||
|
total_disks_size: totalDisksSize
|
||||||
|
total_iops_sec: total_iops_sec
|
||||||
|
total_iops_sec_max: total_iops_sec_max
|
||||||
|
tx_mode: txmode
|
||||||
|
tx_queue_size: tx_queue_size
|
||||||
|
type: type
|
||||||
|
uniq_pools: uniqPools
|
||||||
|
updated_by: updatedBy
|
||||||
|
updated_timestamp: updatedTime
|
||||||
|
user_group_id: userGroupId
|
||||||
|
user_id: userId
|
||||||
|
user_managed: userManaged
|
||||||
|
user_name: username
|
||||||
|
value: value
|
||||||
|
vins_count: vinsConnected
|
||||||
|
vins_ids: vins
|
||||||
|
virtual_image_id: virtualImageId
|
||||||
|
virtual_image_name: virtualImageName
|
||||||
|
vm_ids: vms
|
||||||
|
vnf_ids: vnfs
|
||||||
|
vns_password: vncPasswd
|
||||||
|
volume_id: volumeId
|
||||||
|
without_boot_disk: withoutBootDisk
|
||||||
|
write_bytes_sec: write_bytes_sec
|
||||||
|
write_bytes_sec_max: write_bytes_sec_max
|
||||||
|
write_iops_sec: write_iops_sec
|
||||||
|
write_iops_sec_max: write_iops_sec_max
|
@ -0,0 +1,4 @@
|
|||||||
|
# sdk_path_part: dynamix_path_part
|
||||||
|
add_user: addUser
|
||||||
|
delete_user: deleteUser
|
||||||
|
update_user: updateUser
|
@ -0,0 +1 @@
|
|||||||
|
from ._api import *
|
@ -0,0 +1,6 @@
|
|||||||
|
import dynamix_sdk.base as _base
|
||||||
|
from .usermanager import *
|
||||||
|
|
||||||
|
|
||||||
|
class SystemAPI(_base.BaseAPI):
|
||||||
|
usermanager: SystemUsermanagerAPI
|
@ -0,0 +1 @@
|
|||||||
|
from ._api import *
|
@ -0,0 +1,9 @@
|
|||||||
|
import dynamix_sdk.base as _base
|
||||||
|
from .whoami import *
|
||||||
|
|
||||||
|
|
||||||
|
class SystemUsermanagerAPI(
|
||||||
|
_base.BaseAPI,
|
||||||
|
SystemUsermanagerWhoamiProtocol,
|
||||||
|
):
|
||||||
|
pass
|
@ -0,0 +1,12 @@
|
|||||||
|
import dynamix_sdk.base as _base
|
||||||
|
|
||||||
|
|
||||||
|
class SystemUsermanagerWhoamiResultModel(_base.BaseAPIResultModel):
|
||||||
|
admin: bool
|
||||||
|
name: str
|
||||||
|
roles: list[str]
|
||||||
|
|
||||||
|
|
||||||
|
class SystemUsermanagerWhoamiProtocol(_base.BasePostAPIFunctionProtocol):
|
||||||
|
def whoami(self) -> SystemUsermanagerWhoamiResultModel:
|
||||||
|
...
|
@ -0,0 +1,490 @@
|
|||||||
|
from abc import ABC, abstractmethod
|
||||||
|
from collections.abc import Callable
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from datetime import datetime
|
||||||
|
import inspect
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import time
|
||||||
|
from types import GenericAlias, UnionType
|
||||||
|
from typing import Any, Literal, ParamSpec, Protocol, TypeVar, get_args
|
||||||
|
|
||||||
|
import requests
|
||||||
|
from pydantic import (
|
||||||
|
AliasGenerator,
|
||||||
|
BaseModel as PydanticBaseModel,
|
||||||
|
ConfigDict,
|
||||||
|
PrivateAttr,
|
||||||
|
create_model,
|
||||||
|
)
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
from dynamix_sdk.config import Config, ConfigWithAuth
|
||||||
|
from dynamix_sdk.utils import HTTPMethod, gen_cls_name_from_url_path
|
||||||
|
|
||||||
|
|
||||||
|
NAME_MAPPING_FILE_PATH = os.path.join(
|
||||||
|
os.path.dirname(__file__),
|
||||||
|
'api',
|
||||||
|
'name_mapping.yml',
|
||||||
|
)
|
||||||
|
PATH_MAPPING_FILE_PATH = os.path.join(
|
||||||
|
os.path.dirname(__file__),
|
||||||
|
'api',
|
||||||
|
'path_mapping.yml',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def read_mapping_file(file_path: str):
|
||||||
|
with open(file_path) as file:
|
||||||
|
parsed_data: Any = yaml.safe_load(file)
|
||||||
|
|
||||||
|
if not isinstance(parsed_data, dict):
|
||||||
|
raise TypeError
|
||||||
|
result_dict: dict[Any, Any] = parsed_data
|
||||||
|
|
||||||
|
with open(file_path) as file:
|
||||||
|
name_mapping_file_lines_amount = sum(
|
||||||
|
1 for s in file if s.lstrip() and not s.startswith('#')
|
||||||
|
)
|
||||||
|
|
||||||
|
if len(result_dict) < name_mapping_file_lines_amount:
|
||||||
|
raise AssertionError(
|
||||||
|
f'File {file_path} contains more code lines than'
|
||||||
|
f' keys in the parsed data. Check the file for duplicate keys.'
|
||||||
|
)
|
||||||
|
|
||||||
|
for k, v in result_dict.items():
|
||||||
|
if not isinstance(k, str) or not isinstance(v, str):
|
||||||
|
raise TypeError
|
||||||
|
result_str_dict: dict[str, str] = result_dict
|
||||||
|
|
||||||
|
return result_str_dict
|
||||||
|
|
||||||
|
|
||||||
|
path_mapping_dict = read_mapping_file(PATH_MAPPING_FILE_PATH)
|
||||||
|
|
||||||
|
|
||||||
|
name_mapping_dict = read_mapping_file(NAME_MAPPING_FILE_PATH)
|
||||||
|
common_mappings_values = [
|
||||||
|
v for k, v in name_mapping_dict.items() if '__' not in k
|
||||||
|
]
|
||||||
|
if len(common_mappings_values) > len(set(common_mappings_values)):
|
||||||
|
raise AssertionError(
|
||||||
|
f'File {NAME_MAPPING_FILE_PATH} can contain duplicate values'
|
||||||
|
f' only for individual mapping (attr_name__model_class_name),'
|
||||||
|
f' not common. Check common mappings for duplicate values.'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class BaseAPIFunctionProtocol(Protocol):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class BasePostAPIFunctionProtocol(BaseAPIFunctionProtocol):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class BaseGetAPIFunctionProtocol(BaseAPIFunctionProtocol):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class BaseModel(PydanticBaseModel, ABC):
|
||||||
|
@staticmethod
|
||||||
|
def _get_datetime_from_timestamp(timestamp: float) -> None | datetime:
|
||||||
|
if timestamp > 0:
|
||||||
|
return datetime.fromtimestamp(timestamp)
|
||||||
|
|
||||||
|
|
||||||
|
class BaseModelWithFrozenStrictExtraForbid(BaseModel, ABC):
|
||||||
|
model_config = ConfigDict(
|
||||||
|
extra='forbid',
|
||||||
|
strict=True,
|
||||||
|
frozen=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class BaseAPIParamsModel(BaseModelWithFrozenStrictExtraForbid, ABC):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class BaseAPIParamsNestedModel(BaseModelWithFrozenStrictExtraForbid, ABC):
|
||||||
|
def __init_subclass__(
|
||||||
|
cls,
|
||||||
|
*args: tuple[Any],
|
||||||
|
**kwargs: dict[str, Any],
|
||||||
|
) -> None:
|
||||||
|
super().__init_subclass__(*args, **kwargs)
|
||||||
|
|
||||||
|
postfix = 'APIParamsNM'
|
||||||
|
if not cls.__qualname__.endswith(postfix):
|
||||||
|
raise ValueError(
|
||||||
|
f'Name of {cls} must end with {postfix}.',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class APIResultContext:
|
||||||
|
api_params: BaseAPIParamsModel
|
||||||
|
http_response: requests.Response
|
||||||
|
|
||||||
|
|
||||||
|
class BaseAPIResult(ABC):
|
||||||
|
_api_params: BaseAPIParamsModel
|
||||||
|
_http_response: requests.Response
|
||||||
|
|
||||||
|
|
||||||
|
class BaseAPIResultModel(
|
||||||
|
BaseModelWithFrozenStrictExtraForbid,
|
||||||
|
BaseAPIResult,
|
||||||
|
ABC,
|
||||||
|
):
|
||||||
|
_api_params: BaseAPIParamsModel = PrivateAttr()
|
||||||
|
_http_response: requests.Response = PrivateAttr()
|
||||||
|
|
||||||
|
def model_post_init(self, __context: APIResultContext):
|
||||||
|
self._api_params = __context.api_params
|
||||||
|
self._http_response = __context.http_response
|
||||||
|
|
||||||
|
|
||||||
|
class BaseAPIResultNestedModel(BaseModelWithFrozenStrictExtraForbid, ABC):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class BaseAPIResultBasicType(BaseAPIResult, ABC):
|
||||||
|
_frozen: bool = False
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __new__(cls, value: Any, context: APIResultContext):
|
||||||
|
return super().__new__(cls)
|
||||||
|
|
||||||
|
def __setattr__(self, name: str, value: Any) -> None:
|
||||||
|
if self._frozen:
|
||||||
|
raise AttributeError(
|
||||||
|
'Instance is frozen.',
|
||||||
|
)
|
||||||
|
return super().__setattr__(name, value)
|
||||||
|
|
||||||
|
|
||||||
|
class BaseAPIResultStr(str, BaseAPIResultBasicType, ABC):
|
||||||
|
def __new__(cls, value: str, context: APIResultContext):
|
||||||
|
instance = super().__new__(cls, value)
|
||||||
|
instance._api_params = context.api_params
|
||||||
|
instance._http_response = context.http_response
|
||||||
|
instance._frozen = True
|
||||||
|
return instance
|
||||||
|
|
||||||
|
|
||||||
|
class BaseAPIResultInt(int, BaseAPIResultBasicType, ABC):
|
||||||
|
def __new__(cls, value: int, context: APIResultContext):
|
||||||
|
instance = super().__new__(cls, value)
|
||||||
|
instance._api_params = context.api_params
|
||||||
|
instance._http_response = context.http_response
|
||||||
|
instance._frozen = True
|
||||||
|
return instance
|
||||||
|
|
||||||
|
|
||||||
|
class BaseAPIResultBool(BaseAPIResultBasicType, ABC):
|
||||||
|
value: bool
|
||||||
|
|
||||||
|
def __bool__(self):
|
||||||
|
return self.value
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f'{self.__class__.__qualname__}: {self.value}'
|
||||||
|
|
||||||
|
def __new__(cls, value: bool, context: APIResultContext):
|
||||||
|
if not isinstance(value, bool):
|
||||||
|
raise TypeError
|
||||||
|
instance = super().__new__(cls, value, context)
|
||||||
|
instance.value = value
|
||||||
|
instance._api_params = context.api_params
|
||||||
|
instance._http_response = context.http_response
|
||||||
|
instance._frozen = True
|
||||||
|
return instance
|
||||||
|
|
||||||
|
|
||||||
|
def set_alias_gen(
|
||||||
|
model_cls: type[BaseModel],
|
||||||
|
alias_type: Literal['validation', 'serialization'],
|
||||||
|
name_mapping_dict: dict[str, str]
|
||||||
|
):
|
||||||
|
if model_cls.model_config.get('alias_generator'):
|
||||||
|
return
|
||||||
|
|
||||||
|
def get_model_classes_from_annotation(
|
||||||
|
annotation: type[Any] | None,
|
||||||
|
classes: list[type[BaseModel]] | None = None,
|
||||||
|
):
|
||||||
|
_classes = classes or []
|
||||||
|
if annotation:
|
||||||
|
if isinstance(annotation, (UnionType, GenericAlias)):
|
||||||
|
for cls in get_args(annotation):
|
||||||
|
_classes += get_model_classes_from_annotation(cls)
|
||||||
|
elif issubclass(annotation, BaseModel):
|
||||||
|
_classes.append(annotation)
|
||||||
|
return _classes
|
||||||
|
|
||||||
|
for field in model_cls.model_fields.values():
|
||||||
|
for cls in get_model_classes_from_annotation(field.annotation):
|
||||||
|
set_alias_gen(
|
||||||
|
model_cls=cls,
|
||||||
|
alias_type=alias_type,
|
||||||
|
name_mapping_dict=name_mapping_dict,
|
||||||
|
)
|
||||||
|
|
||||||
|
def alias_gen(field_name: str):
|
||||||
|
individual_alias = name_mapping_dict.get(
|
||||||
|
f'{field_name}__{model_cls.__qualname__}',
|
||||||
|
)
|
||||||
|
if individual_alias:
|
||||||
|
return individual_alias
|
||||||
|
else:
|
||||||
|
if field_name in name_mapping_dict:
|
||||||
|
return name_mapping_dict[field_name]
|
||||||
|
else:
|
||||||
|
raise KeyError(
|
||||||
|
f'{field_name} not found in name mapping dictionary.'
|
||||||
|
f' Class model: {model_cls.__name__}.'
|
||||||
|
)
|
||||||
|
|
||||||
|
kwargs = {
|
||||||
|
f'{alias_type}_alias': alias_gen
|
||||||
|
}
|
||||||
|
|
||||||
|
model_cls.model_config['alias_generator'] = AliasGenerator(**kwargs)
|
||||||
|
model_cls.model_rebuild(force=True)
|
||||||
|
|
||||||
|
|
||||||
|
params_model_classes: dict[str, type[BaseAPIParamsModel]] = {}
|
||||||
|
|
||||||
|
|
||||||
|
APIParamsP = ParamSpec('APIParamsP')
|
||||||
|
APIResultT = TypeVar(
|
||||||
|
'APIResultT',
|
||||||
|
bound=BaseAPIResultModel | BaseAPIResultBasicType,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class BaseAPI(ABC):
|
||||||
|
_config: Config
|
||||||
|
_base_api_path: None | str
|
||||||
|
_path_mapping_dict: dict[str, str] = path_mapping_dict
|
||||||
|
_last_call_api_path: None | str = None
|
||||||
|
_name_mapping_dict: dict[str, str] = name_mapping_dict
|
||||||
|
_post_json: bool = True
|
||||||
|
|
||||||
|
def __init_subclass__(
|
||||||
|
cls,
|
||||||
|
path_mapping_dict: None | dict[str, str] = None,
|
||||||
|
name_mapping_dict: None | dict[str, str] = None,
|
||||||
|
post_json: None | bool = None,
|
||||||
|
) -> None:
|
||||||
|
if path_mapping_dict:
|
||||||
|
cls._path_mapping_dict = path_mapping_dict
|
||||||
|
if name_mapping_dict:
|
||||||
|
cls._name_mapping_dict = name_mapping_dict
|
||||||
|
if post_json is not None:
|
||||||
|
cls._post_json = post_json
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
config: Config,
|
||||||
|
base_api_path: None | str = None
|
||||||
|
):
|
||||||
|
self._config = config
|
||||||
|
self._base_api_path = base_api_path
|
||||||
|
|
||||||
|
def __getattribute__(self, name: str) -> Any:
|
||||||
|
if name.startswith('_'):
|
||||||
|
return super().__getattribute__(name)
|
||||||
|
else:
|
||||||
|
path_part = self._path_mapping_dict.get(name, name)
|
||||||
|
if name in self.__annotations__:
|
||||||
|
annotation = self.__annotations__[name]
|
||||||
|
if issubclass(annotation, BaseAPI):
|
||||||
|
api_cls = annotation
|
||||||
|
return api_cls(
|
||||||
|
config=self._config,
|
||||||
|
base_api_path=(
|
||||||
|
f'{self._base_api_path or ""}/{path_part}'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self._last_call_api_path = (
|
||||||
|
f'{self._base_api_path or ""}/{path_part}'
|
||||||
|
)
|
||||||
|
|
||||||
|
attr_value = super().__getattribute__(name)
|
||||||
|
if not inspect.ismethod(attr_value):
|
||||||
|
raise ValueError
|
||||||
|
|
||||||
|
return self._make_api_function(attr_value)
|
||||||
|
|
||||||
|
def _make_api_function(
|
||||||
|
self,
|
||||||
|
protocol_method: Callable[APIParamsP, APIResultT],
|
||||||
|
/,
|
||||||
|
) -> Callable[APIParamsP, APIResultT]:
|
||||||
|
return_type = inspect.signature(protocol_method).return_annotation
|
||||||
|
if not issubclass(return_type, get_args(APIResultT.__bound__)):
|
||||||
|
raise TypeError(
|
||||||
|
f'Return type annotation of {protocol_method}'
|
||||||
|
f' must be subclass of {get_args(APIResultT.__bound__)}.'
|
||||||
|
)
|
||||||
|
api_result_cls: type[APIResultT] = return_type
|
||||||
|
|
||||||
|
def api_function(
|
||||||
|
*args: APIParamsP.args,
|
||||||
|
**kwargs: APIParamsP.kwargs,
|
||||||
|
):
|
||||||
|
config = self._config
|
||||||
|
|
||||||
|
if self._last_call_api_path:
|
||||||
|
api_path = self._last_call_api_path
|
||||||
|
else:
|
||||||
|
raise ValueError
|
||||||
|
|
||||||
|
api_params_cls_name = gen_cls_name_from_url_path(
|
||||||
|
url_path=re.sub(r'[\[\]]', '', api_path),
|
||||||
|
postfix=BaseAPIParamsModel.__qualname__.removeprefix(
|
||||||
|
'BaseAPI'
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
api_params_cls = params_model_classes.get(
|
||||||
|
api_params_cls_name,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
if not api_params_cls:
|
||||||
|
field_definitions = {}
|
||||||
|
parameters = inspect.signature(protocol_method).parameters
|
||||||
|
inspect_empty = inspect.Parameter.empty
|
||||||
|
for p in parameters.values():
|
||||||
|
field_definitions[p.name] = (
|
||||||
|
p.annotation,
|
||||||
|
... if p.default is inspect_empty else p.default,
|
||||||
|
)
|
||||||
|
|
||||||
|
api_params_cls = create_model(
|
||||||
|
api_params_cls_name,
|
||||||
|
__base__=BaseAPIParamsModel,
|
||||||
|
__module__=api_result_cls.__module__,
|
||||||
|
**field_definitions,
|
||||||
|
)
|
||||||
|
params_model_classes[api_params_cls_name] = api_params_cls
|
||||||
|
|
||||||
|
set_alias_gen(
|
||||||
|
model_cls=api_params_cls,
|
||||||
|
alias_type='serialization',
|
||||||
|
name_mapping_dict=self._name_mapping_dict,
|
||||||
|
)
|
||||||
|
|
||||||
|
api_params = api_params_cls(*args, **kwargs)
|
||||||
|
|
||||||
|
req_headers = None
|
||||||
|
if isinstance(config, ConfigWithAuth):
|
||||||
|
req_headers = {
|
||||||
|
'Authorization': f'bearer {config.jwt}',
|
||||||
|
}
|
||||||
|
|
||||||
|
model_data = api_params.model_dump(
|
||||||
|
by_alias=True,
|
||||||
|
exclude_none=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
for api_mixin_cls in self.__class__.__bases__[1:]:
|
||||||
|
if hasattr(api_mixin_cls, protocol_method.__name__):
|
||||||
|
if issubclass(api_mixin_cls, BasePostAPIFunctionProtocol):
|
||||||
|
http_method = HTTPMethod.POST
|
||||||
|
break
|
||||||
|
elif issubclass(api_mixin_cls, BaseGetAPIFunctionProtocol):
|
||||||
|
http_method = HTTPMethod.GET
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
raise RuntimeError
|
||||||
|
|
||||||
|
req_params = None
|
||||||
|
req_json = None
|
||||||
|
req_data = None
|
||||||
|
match http_method:
|
||||||
|
case HTTPMethod.GET:
|
||||||
|
req_params = model_data
|
||||||
|
case HTTPMethod.POST:
|
||||||
|
if self._post_json:
|
||||||
|
req_json = model_data
|
||||||
|
else:
|
||||||
|
req_data = model_data
|
||||||
|
case _:
|
||||||
|
raise RuntimeError
|
||||||
|
|
||||||
|
http_request = requests.Request(
|
||||||
|
method=http_method,
|
||||||
|
url=config.get_api_url(api_path=api_path),
|
||||||
|
headers=req_headers,
|
||||||
|
params=req_params,
|
||||||
|
json=req_json,
|
||||||
|
data=req_data,
|
||||||
|
).prepare()
|
||||||
|
|
||||||
|
attempts = config.http503_attempts
|
||||||
|
with requests.Session() as session:
|
||||||
|
while True:
|
||||||
|
http_response = session.send(
|
||||||
|
request=http_request,
|
||||||
|
verify=config.verify_ssl,
|
||||||
|
)
|
||||||
|
|
||||||
|
if http_response.status_code == 503:
|
||||||
|
if attempts < 1:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
attempts -= 1
|
||||||
|
time.sleep(config.http503_attempts_interval)
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
|
||||||
|
http_response.raise_for_status()
|
||||||
|
|
||||||
|
api_result_context = APIResultContext(
|
||||||
|
api_params=api_params,
|
||||||
|
http_response=http_response,
|
||||||
|
)
|
||||||
|
|
||||||
|
if issubclass(api_result_cls, BaseAPIResultModel):
|
||||||
|
set_alias_gen(
|
||||||
|
model_cls=api_result_cls,
|
||||||
|
alias_type='validation',
|
||||||
|
name_mapping_dict=self._name_mapping_dict,
|
||||||
|
)
|
||||||
|
|
||||||
|
result_extra_allow = (
|
||||||
|
api_result_cls.model_config.get('extra') == 'allow'
|
||||||
|
)
|
||||||
|
if config.result_extra_allow != result_extra_allow:
|
||||||
|
if config.result_extra_allow:
|
||||||
|
api_result_cls.model_config['extra'] = 'allow'
|
||||||
|
else:
|
||||||
|
api_result_cls.model_config['extra'] = (
|
||||||
|
BaseAPIResultModel.model_config.get('extra')
|
||||||
|
)
|
||||||
|
api_result_cls.model_rebuild(force=True)
|
||||||
|
|
||||||
|
api_result = api_result_cls.model_validate_json(
|
||||||
|
json_data=http_response.content,
|
||||||
|
context=api_result_context,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
decoded_content = http_response.json()
|
||||||
|
except requests.JSONDecodeError:
|
||||||
|
decoded_content = http_response.text
|
||||||
|
|
||||||
|
api_result = api_result_cls(
|
||||||
|
value=decoded_content,
|
||||||
|
context=api_result_context,
|
||||||
|
)
|
||||||
|
|
||||||
|
return api_result
|
||||||
|
|
||||||
|
return api_function
|
@ -0,0 +1,92 @@
|
|||||||
|
from dynamix_sdk import base, config
|
||||||
|
|
||||||
|
|
||||||
|
class BVSAuth(config.AuthenticatorProtocol):
|
||||||
|
_config: config.BaseConfigWithDomain
|
||||||
|
client_id: str
|
||||||
|
client_secret: str
|
||||||
|
password: str
|
||||||
|
user_name: str
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
url: str,
|
||||||
|
domain: str,
|
||||||
|
client_id: str,
|
||||||
|
client_secret: str,
|
||||||
|
user_name: str,
|
||||||
|
password: str,
|
||||||
|
verify_ssl: bool = True,
|
||||||
|
http503_attempts: int = 10,
|
||||||
|
http503_attempts_interval: int = 5,
|
||||||
|
result_extra_allow: bool = True,
|
||||||
|
):
|
||||||
|
self._config = config.BaseConfigWithDomain(
|
||||||
|
url=url,
|
||||||
|
verify_ssl=verify_ssl,
|
||||||
|
domain=domain,
|
||||||
|
http503_attempts=http503_attempts,
|
||||||
|
http503_attempts_interval=http503_attempts_interval,
|
||||||
|
result_extra_allow=result_extra_allow,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.client_id = client_id
|
||||||
|
self.client_secret = client_secret
|
||||||
|
self.user_name = user_name
|
||||||
|
self.password = password
|
||||||
|
|
||||||
|
@property
|
||||||
|
def api(self):
|
||||||
|
return BVSAPI(config=self._config)
|
||||||
|
|
||||||
|
def get_jwt(self):
|
||||||
|
return self.api.token(
|
||||||
|
client_id=self.client_id,
|
||||||
|
client_secret=self.client_secret,
|
||||||
|
grant_type='password',
|
||||||
|
password=self.password,
|
||||||
|
response_type='token',
|
||||||
|
scope='openid',
|
||||||
|
user_name=self.user_name,
|
||||||
|
).access_token
|
||||||
|
|
||||||
|
|
||||||
|
class BVSTokenResult(base.BaseAPIResultModel):
|
||||||
|
access_token: str
|
||||||
|
|
||||||
|
|
||||||
|
class BVSTokenProtocol(base.BasePostAPIFunctionProtocol):
|
||||||
|
def token(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
client_id: str,
|
||||||
|
client_secret: str,
|
||||||
|
grant_type: str,
|
||||||
|
password: str,
|
||||||
|
response_type: str,
|
||||||
|
scope: str,
|
||||||
|
user_name: str,
|
||||||
|
) -> BVSTokenResult:
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
class BVSAPI(
|
||||||
|
base.BaseAPI,
|
||||||
|
BVSTokenProtocol,
|
||||||
|
path_mapping_dict={
|
||||||
|
'token': 'realms/[domain]/protocol/openid-connect/token',
|
||||||
|
},
|
||||||
|
name_mapping_dict={
|
||||||
|
'access_token': 'access_token',
|
||||||
|
'client_id': 'client_id',
|
||||||
|
'client_secret': 'client_secret',
|
||||||
|
'grant_type': 'grant_type',
|
||||||
|
'password': 'password',
|
||||||
|
'response_type': 'response_type',
|
||||||
|
'scope': 'scope',
|
||||||
|
'user_name': 'username',
|
||||||
|
'user_name': 'username',
|
||||||
|
},
|
||||||
|
post_json=False,
|
||||||
|
):
|
||||||
|
pass
|
@ -0,0 +1,45 @@
|
|||||||
|
from dataclasses import dataclass
|
||||||
|
import re
|
||||||
|
from typing import Protocol
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(kw_only=True)
|
||||||
|
class Config:
|
||||||
|
url: str
|
||||||
|
base_api_path: str = ''
|
||||||
|
verify_ssl: bool
|
||||||
|
http503_attempts: int = 10
|
||||||
|
http503_attempts_interval: int = 5
|
||||||
|
result_extra_allow: bool = False
|
||||||
|
|
||||||
|
def get_api_url(self, api_path: str):
|
||||||
|
substitutions = re.findall(r'\[\w+\]', api_path)
|
||||||
|
_api_path = api_path[:]
|
||||||
|
for s in substitutions:
|
||||||
|
attr_name = f'{s.strip("[]")}'
|
||||||
|
attr_value = getattr(self, attr_name)
|
||||||
|
_api_path = _api_path.replace(s, attr_value)
|
||||||
|
|
||||||
|
return f'{self.url}{self.base_api_path}{_api_path}'
|
||||||
|
|
||||||
|
|
||||||
|
class AuthenticatorProtocol(Protocol):
|
||||||
|
def get_jwt(self) -> str:
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(kw_only=True)
|
||||||
|
class ConfigWithAuth(Config):
|
||||||
|
auth: str | AuthenticatorProtocol
|
||||||
|
|
||||||
|
@property
|
||||||
|
def jwt(self):
|
||||||
|
if isinstance(self.auth, str):
|
||||||
|
return self.auth
|
||||||
|
else:
|
||||||
|
return self.auth.get_jwt()
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(kw_only=True)
|
||||||
|
class BaseConfigWithDomain(Config):
|
||||||
|
domain: str
|
@ -0,0 +1,74 @@
|
|||||||
|
from dynamix_sdk import base, config
|
||||||
|
|
||||||
|
|
||||||
|
class DECS3OAuth(config.AuthenticatorProtocol):
|
||||||
|
_config: config.Config
|
||||||
|
client_id: str
|
||||||
|
client_secret: str
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
url: str,
|
||||||
|
client_id: str,
|
||||||
|
client_secret: str,
|
||||||
|
verify_ssl: bool = True,
|
||||||
|
http503_attempts: int = 10,
|
||||||
|
http503_attempts_interval: int = 5,
|
||||||
|
result_extra_allow: bool = True,
|
||||||
|
):
|
||||||
|
self._config = config.Config(
|
||||||
|
base_api_path='/v1',
|
||||||
|
url=url,
|
||||||
|
verify_ssl=verify_ssl,
|
||||||
|
http503_attempts=http503_attempts,
|
||||||
|
http503_attempts_interval=http503_attempts_interval,
|
||||||
|
result_extra_allow=result_extra_allow,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.client_id = client_id
|
||||||
|
self.client_secret = client_secret
|
||||||
|
|
||||||
|
@property
|
||||||
|
def api(self):
|
||||||
|
return DECS3OAPI(config=self._config)
|
||||||
|
|
||||||
|
def get_jwt(self):
|
||||||
|
return self.api.oauth__access_token(
|
||||||
|
client_id=self.client_id,
|
||||||
|
client_secret=self.client_secret,
|
||||||
|
grant_type='client_credentials',
|
||||||
|
response_type='id_token',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class DECS3OOauthAccesstokenResultStr(base.BaseAPIResultStr):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class DECS3OOauthAccesstokenProtocol(base.BasePostAPIFunctionProtocol):
|
||||||
|
def oauth__access_token(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
client_id: str,
|
||||||
|
client_secret: str,
|
||||||
|
grant_type: None | str = None,
|
||||||
|
response_type: None | str = None,
|
||||||
|
validity: None | int = None,
|
||||||
|
) -> DECS3OOauthAccesstokenResultStr:
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
class DECS3OAPI(
|
||||||
|
base.BaseAPI,
|
||||||
|
DECS3OOauthAccesstokenProtocol,
|
||||||
|
path_mapping_dict={'oauth__access_token': 'oauth/access_token'},
|
||||||
|
name_mapping_dict={
|
||||||
|
'client_id': 'client_id',
|
||||||
|
'client_secret': 'client_secret',
|
||||||
|
'grant_type': 'grant_type',
|
||||||
|
'response_type': 'response_type',
|
||||||
|
'validity': 'validity',
|
||||||
|
},
|
||||||
|
post_json=False,
|
||||||
|
):
|
||||||
|
pass
|
@ -0,0 +1,30 @@
|
|||||||
|
from dynamix_sdk import config
|
||||||
|
from .api import API
|
||||||
|
|
||||||
|
|
||||||
|
class Dynamix:
|
||||||
|
_config: config.ConfigWithAuth
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
url: str,
|
||||||
|
auth: str | config.AuthenticatorProtocol,
|
||||||
|
verify_ssl: bool = True,
|
||||||
|
http503_attempts: int = 10,
|
||||||
|
http503_attempts_interval: int = 5,
|
||||||
|
result_extra_allow: bool = False,
|
||||||
|
):
|
||||||
|
self._config = config.ConfigWithAuth(
|
||||||
|
base_api_path='/restmachine',
|
||||||
|
url=url,
|
||||||
|
auth=auth,
|
||||||
|
verify_ssl=verify_ssl,
|
||||||
|
http503_attempts=http503_attempts,
|
||||||
|
http503_attempts_interval=http503_attempts_interval,
|
||||||
|
result_extra_allow=result_extra_allow,
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def api(self):
|
||||||
|
return API(config=self._config)
|
@ -0,0 +1,10 @@
|
|||||||
|
from .base import (
|
||||||
|
BaseAPIParamsModel,
|
||||||
|
BaseAPIParamsNestedModel,
|
||||||
|
BaseAPIResultModel,
|
||||||
|
BaseAPIResultNestedModel,
|
||||||
|
BaseAPIResultStr,
|
||||||
|
BaseAPIResultInt,
|
||||||
|
BaseAPIResultBool,
|
||||||
|
)
|
||||||
|
from .api import *
|
@ -0,0 +1,21 @@
|
|||||||
|
from enum import Enum, auto as enum_auto
|
||||||
|
|
||||||
|
|
||||||
|
class AutoNameEnum(Enum):
|
||||||
|
def _generate_next_value_(name, start, count, last_values):
|
||||||
|
return name
|
||||||
|
|
||||||
|
|
||||||
|
class EmptyStr(str, Enum):
|
||||||
|
EMPTY_STR = ''
|
||||||
|
|
||||||
|
|
||||||
|
class HTTPMethod(str, AutoNameEnum):
|
||||||
|
POST = enum_auto()
|
||||||
|
GET = enum_auto()
|
||||||
|
|
||||||
|
|
||||||
|
def gen_cls_name_from_url_path(url_path: str, postfix: str = ''):
|
||||||
|
parts = url_path.strip('/').replace('-', '').split('/')
|
||||||
|
base = ''.join(f'{p[0].upper()}{p[1:]}' for p in parts)
|
||||||
|
return f'{base}{postfix}'
|
Loading…
Reference in new issue