first commit
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
"""openstacksdk connection. IAM token is 24h; sdk refreshes on authorize()."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Iterator
|
||||
from typing import Any
|
||||
|
||||
from gpu_rent.config import Config
|
||||
from gpu_rent.errors import CloudError
|
||||
|
||||
RESOURCE_TAG = "gpu-rent"
|
||||
COMPUTE_MICROVERSION = "2.72"
|
||||
|
||||
|
||||
def connect(cfg: Config):
|
||||
try:
|
||||
import openstack
|
||||
except ImportError as exc:
|
||||
raise CloudError("Нет openstacksdk. Переустанови пакет: pip install -e .") from exc
|
||||
|
||||
try:
|
||||
conn = openstack.connect(
|
||||
auth_url=cfg.os_auth_url,
|
||||
project_id=cfg.os_project_id,
|
||||
username=cfg.os_username,
|
||||
password=cfg.os_password,
|
||||
user_domain_name=cfg.os_user_domain_name,
|
||||
project_domain_name=cfg.os_user_domain_name,
|
||||
region_name=cfg.os_region_name,
|
||||
identity_api_version="3",
|
||||
interface="public",
|
||||
compute_api_version=COMPUTE_MICROVERSION,
|
||||
app_name="gpu-rent",
|
||||
app_version="0.1.0",
|
||||
)
|
||||
conn.authorize()
|
||||
except Exception as exc:
|
||||
raise CloudError(
|
||||
"Keystone не выдал токен. Проверь OS_USERNAME / OS_PASSWORD / "
|
||||
"OS_PROJECT_ID / OS_USER_DOMAIN_NAME (номер аккаунта). "
|
||||
"Не используй X-Token панели. Подробности: docs/setup.md. "
|
||||
f"Ошибка SDK: {exc}"
|
||||
) from exc
|
||||
return conn
|
||||
|
||||
|
||||
def _obj_dict(obj: Any) -> dict[str, Any]:
|
||||
if obj is None:
|
||||
return {}
|
||||
if hasattr(obj, "to_dict"):
|
||||
try:
|
||||
return obj.to_dict(computed=False)
|
||||
except TypeError:
|
||||
return obj.to_dict()
|
||||
if isinstance(obj, dict):
|
||||
return obj
|
||||
return {"repr": repr(obj)}
|
||||
|
||||
|
||||
def compute_quotas(conn) -> dict[str, Any]:
|
||||
project = conn.current_project_id
|
||||
try:
|
||||
quota = conn.compute.get_quota_set(project)
|
||||
return _obj_dict(quota)
|
||||
except Exception:
|
||||
try:
|
||||
return dict(conn.get_compute_quotas(project) or {})
|
||||
except Exception as exc:
|
||||
raise CloudError(f"Не прочитать compute quota: {exc}") from exc
|
||||
|
||||
|
||||
def volume_quotas(conn) -> dict[str, Any]:
|
||||
project = conn.current_project_id
|
||||
try:
|
||||
quota = conn.block_storage.get_quota_set(project)
|
||||
return _obj_dict(quota)
|
||||
except Exception:
|
||||
try:
|
||||
return dict(conn.get_volume_quotas(project) or {})
|
||||
except Exception as exc:
|
||||
return {"error": str(exc)}
|
||||
|
||||
|
||||
def iter_flavors(conn) -> Iterator[Any]:
|
||||
yield from conn.compute.flavors(details=True)
|
||||
|
||||
|
||||
def iter_volume_types(conn) -> Iterator[Any]:
|
||||
yield from conn.block_storage.types()
|
||||
|
||||
|
||||
def iter_images(conn) -> Iterator[Any]:
|
||||
yield from conn.image.images()
|
||||
|
||||
|
||||
def find_tagged_servers(conn) -> list[Any]:
|
||||
servers = []
|
||||
for server in conn.compute.servers(details=True):
|
||||
tags = set(getattr(server, "tags", None) or [])
|
||||
name = (getattr(server, "name", "") or "").lower()
|
||||
if RESOURCE_TAG in tags or name.startswith("gpu-rent"):
|
||||
servers.append(server)
|
||||
return servers
|
||||
|
||||
|
||||
def find_volumes_by_name(conn, name: str) -> list[Any]:
|
||||
found = []
|
||||
for volume in conn.block_storage.volumes():
|
||||
if getattr(volume, "name", None) == name:
|
||||
found.append(volume)
|
||||
return found
|
||||
|
||||
|
||||
def find_snapshot_by_name(conn, name: str) -> Any | None:
|
||||
for snap in conn.block_storage.snapshots():
|
||||
if getattr(snap, "name", None) == name:
|
||||
return snap
|
||||
return None
|
||||
Reference in New Issue
Block a user