Files
viktor 4d7a0f354d Приватные сети разобраны на живом API
Раздел переписан по факту поведения платформы, а не по документации.

- номер сети лежит в resource_id, а не id, добавлен vpc_id_of()
- список сетей приходит голым массивом
- при создании принимается только имя, регион и участники только для чтения
- подключение сервера асинхронно и блокирует сервер, добавлен vpc_wait_member()
- отключение участника и удаление сети настойчивые, ждут снятия блокировки

Добавлен пример private_network.py.

Claude-Session: https://claude.ai/code/session_01Loz5stgQZH6ofBdMqTxiJu
2026-08-23 19:34:12 +09:00

8.3 KiB

regcloud-api

Клиент к API облака REG.RU (Рег.облако), точка входа https://api.cloudvps.reg.ru.

Полное покрытие API: серверы и все действия над ними, снимки, образы, тарифы, регионы, SSH-ключи, IP-адреса и обратные записи, приватные сети, kubeconfig кластеров, история операций и биллинг.

Установка

pip install git+https://git.stackworks.ru/viktor/regcloud-api.git

Токен берётся в личном кабинете, в разделе настроек, и кладётся в REGRU_CLOUD_TOKEN.

Осмотреться

from regcloud_api import RegCloud

api = RegCloud()

for r in api.regions():                       # где можно размещаться
    print(r["slug"], r["name"])

for i in api.distributions():                 # операционные системы
    print(i["slug"], i["distribution"])

for i in api.applications():                  # готовые сборки: панели, докер, гитлаб
    print(i["slug"])

for s in api.sizes():                         # тарифы
    print(s["slug"], s["vcpus"], "ядер", s["price"], "р/час")

Во второй версии API образов заметно больше и они разложены по регионам.

for i in api.images_v2("openstack-spb1", type="distribution"):
    print(i["id"], i["name"])

Тарифы

Slug собирается по шаблону c<ядра>-m<память>-d<диск>-<линейка>. Клиент умеет собирать его сам и заодно проверять, что такое сочетание вообще существует.

from regcloud_api import build_size, parse_size

RegCloud.make_size(4, 8, 120, "hp")      # 'c4-m8-d120-hp'
build_size(4, 5, 120, "hp")              # ValueError, при 4 ядрах памяти 5 ГБ не бывает

parse_size("c8-m32-d128-g1-a4000-gpu")
# {'gpu': 'A4000 16 ГБ', 'vcpus': 8, 'memory_gb': 32, 'disk_gb': 128, 'price_hour': 37.8}

Линейки: std стандартный, stdp стандартный плюс, hp производительный, hps производительный ФЗ-152, ddc выделенный CPU, high высокочастотный.

Жизненный цикл сервера

key = api.add_ssh_key("deploy", "~/.ssh/id_ed25519.pub")   # можно путём к файлу

srv = api.create_server(
    size="c2-m4-d60-hp",
    image="ubuntu-24-04-amd64",
    name=api.random_name(),                 # платформа умеет придумывать имена
    region="openstack-msk1",
    ssh_keys=[key["fingerprint"]],
)

info = api.wait_active(srv["id"])
print("адрес:", RegCloud.ip_of(info))

Действия над сервером.

api.stop(id); api.start(id); api.reboot(id)
api.resize(id, "c4-m8-d120-hp")            # сменить тариф
api.rebuild(id, "debian-12-amd64")         # переустановить систему
api.reset_password(id)
api.vnc_link(id)                           # консоль, когда по ssh уже не зайти
api.set_backups(id, True)
api.clone(id, "копия")

Снимки.

api.snapshot(id, "base", offline=True)     # платформа сама остановит сервер
snap = api.wait_snapshot("base")
api.create_server(size="c2-m4-d60-hp", image=snap["id"], region="openstack-msk1")
api.servers_from_snapshot(snap["id"])      # кто уже поднят из этого снимка
api.delete_snapshot(snap["id"])

Удаление.

api.destroy_server(id)                     # дождётся снятия блокировки

Адреса

api.ips(server_id)
api.add_ip(server_id, ipv4=1)
api.set_ptr("1.2.3.4", "mail.example.com")
api.delete_ip("1.2.3.4")

Приватные сети

Серверы в одной приватной сети видят друг друга напрямую, минуя интернет. Трафик внутри не тарифицируется, а машине-исполнителю можно не выдавать публичный адрес вовсе.

net = api.create_vpc("backoffice")          # кроме имени платформа ничего не принимает
net_id = RegCloud.vpc_id_of(net)            # номер лежит в resource_id, а не в id

api.vpc_attach(net_id, server_id)           # действие асинхронное
api.vpc_wait_member(net_id, server_id)      # дожидаемся, пока сервер реально войдёт

api.vpc_members(net_id)                     # список номеров серверов
api.rename_vpc(net_id, "новое имя")

api.vpc_detach(net_id, server_id)
api.delete_vpc(net_id)

Что выяснено на живом API и чего нет в документации.

Номер сети лежит в поле resource_id, а не id. Список сетей приходит голым массивом, без обёртки. При создании принимается только имя, а регион, участники и resource_id объявлены только для чтения и проставляются платформой. Подключение сервера к сети асинхронно, и пока оно не доиграет, сервер заблокирован, из-за чего не выйдет ни отключить его, ни удалить сеть. Поэтому vpc_detach() и delete_vpc() тут настойчивые, повторяют попытки, пока блокировка не снимется.

Деньги

api.money_left()          # сколько на счету
api.burn_rate()           # сколько капает в час, в сутки и в месяц
api.billing_history()
api.history(limit=50)     # что и когда делали с ресурсами
api.prices()

Ошибки

Все ошибки платформы разложены по смыслу, чтобы ловить прицельно.

from regcloud_api import NotFound, Locked, ValidationError, InsufficientFunds

try:
    api.destroy_server(123)
except NotFound:
    pass                       # его уже нет, и хорошо
except Locked:
    pass                       # занят другой операцией

Особенности платформы, обойдённые внутри

Собрано на живых серверах, чтобы вы на это не наступали.

Адрес сервера лежит в поле ip. Поле networks из документации всегда пустое. RegCloud.ip_of() смотрит в оба места.

Снимок снимается только с работающего сервера. У остановленного платформа отвечает SERVER_IS_STOPPED, останавливать его должна она сама по параметру offline.

После снимка сервер сидит в locked и на удаление отвечает RESOURCE_DELETE_ERROR. Отпускает примерно через полминуты, поэтому destroy_server() повторяет попытки. Забытый сервер продолжает тарифицироваться, молча сдаваться тут нельзя.

sizes() возвращает не все линейки. Тарифы с видеокартами в выдачу не попадают, хотя создание с ними работает. Их список лежит в gpu_sizes() и в docs_slugs.md.

Тарификация идёт от часа. Двадцать минут работы списываются как полный час.

Рядом

  • docs_slugs.md — тарифы, образы, регионы, правила составления slug'ов
  • openapi_v1.json — спецификация API, снятая с сервера платформы
  • examples/ — примеры