Автоматизация с Proxmox API: Лесни скриптове

Автоматизация с Proxmox API: Лесни скриптове

Здравейте, колеги! В днешната динамична ИТ среда, където скоростта и ефективността са всичко, автоматизацията не е просто удобство, а необходимост. Ако вашата инфраструктура се управлява от Proxmox VE, вие вече имате достъп до един от най-мощните инструменти за виртуализация с отворен код. Но истинската магия започва, когато започнете да говорите с него на неговия език – чрез Proxmox API.

В тази статия ще разгледаме как да създаваме лесни, но мощни скриптове, които ще трансформират начина ви на работа.

Какво всъщност е Proxmox API и защо трябва да ви интересува?

API (Application Programming Interface) е просто набор от правила, които позволяват на различни софтуери да комуникират помежду си. Мислете за него като за щепсел – вашият скрипт се „заключва“ в Proxmox и му казва какво да прави.

Защо да се занимавате с него?

  • Ефективност: Автоматизирайте повтарящи се задачи като създаване на виртуални машини, правене на бекъпи или рестартиране на услуги с една команда.
  • Скорост: Операции, които отнемат минути чрез уеб интерфейса, се изпълняват за секунди.
  • Интеграция: Вградете управлението на Proxmox във вашите собствени приложения, системи за мониторинг (като Zabbix или Nagios) или пайплайни за CI/CD (като GitLab CI).
  • Консистентност: Скриптовете елиминират човешката грешка. Всяка нова VM, създадена от вашия скрипт, ще бъде идентична на предходната.

Proxmox API е RESTful, което означава, че използва стандартни HTTP методи (GET, POST, PUT, DELETE), с които много от нас вече са запознати. Това го прави достъпен и лесен за употреба.


Първи стъпки: Влизане в системата и удостоверяване

Преди да можете да командувате вашия клъстър, трябва да се удостоверите. Proxmox предлага два основни начина:

  1. Парола за потребител: Лесно за започване, но по-малко сигурно.
  2. API Token (Токен): Препоръчителният и по-сигурен метод. Токените могат да бъдат създадени за конкретен потребител с конкретни права (разрешения).

Ето как да създадете токен през уеб интерфейса:

  • Отидете в Datacenter -> Permissions -> API Tokens.
  • Щракнете върху Add.
  • Изберете потребител и задайте име на токена (напр. ansible@mytoken).

Запазете SECRET_TOKEN на сигурно място! Той се показва само веднъж.


Инструментите на занаята: cURL, Bash и Python

Можете да взаимодействате с API-то с почти всеки език за програмиране, но ще се съсредоточим върху два най-достъпни инструмента.

Сценарий 1: Бързината на Bash и cURL

cURL е швейцарското ножче за мрежовите взаимодействия в командния ред. Перфектно е за бързи проверки и прости скриптове.

Пример 1: Извличане на списък с всички виртуални машини

Първо, нека се удостоверим. Ще използваме "ticket" базирана на парола за удостоверяване за простота.

#!/bin/bash

# Конфигурационни променливи
PM_NODE="pve1"
PM_USER="root@pam"
PM_PASS="your_secure_password"
PM_URL="https://$PM_NODE:8006/api2/json"

# 1. Удостоверяване и получаване на билет (ticket)
AUTH_JSON=$(curl -s -k -d "username=$PM_USER&password=$PM_PASS" $PM_URL/access/ticket)
AUTH_TICKET=$(echo $AUTH_JSON | jq -r '.data.ticket')
AUTH_CSRF=$(echo $AUTH_JSON | jq -r '.data.CSRFPreventionToken')

# 2. Използване на билета за заявка към списъка с VMs
curl -s -k --cookie "PVEAuthCookie=$AUTH_TICKET" -H "CSRFPreventionToken: $AUTH_CSRF" $PM_URL/cluster/resources | jq '.data[] | select(.type == "qemu")'

Обяснение:

  • curl -s -k ...-s е за "silent", -k е за "ignore certificate warning" (полезно за тестване със самоподписан сертификат).
  • jq: Това е незаменим инструмент за командния ред за работа с JSON. В първата стъпка той "изважда" (-r за "raw") стойностите на ticket и CSRFPreventionToken от отговора на API-то.
  • Втората заявка използва билета като бисквитка и добавя CSRF токена в заглавието (header) за сигурност.

Пример 2: Спиране на виртуална машина по ID

#!/bin/bash

# ... (променливи за удостоверяване от предишния пример)

VM_ID="100"

# Командата за "shutdown" на VM
curl -s -k -X POST --cookie "PVEAuthCookie=$AUTH_TICKET" -H "CSRFPreventionToken: $AUTH_CSRF" $PM_URL/nodes/$PM_NODE/qemu/$VM_ID/status/shutdown

Вижте как URL адресът следва логична структура: /nodes/[ИМЕ_НА_НОДА]/qemu/[ID_НА_VM]/status/shutdown.

Сценарий 2: Гъвкавостта на Python

За по-сложни задачи, Python с неговата requests библиотека е идеален избор. Той предлага по-добра обработка на грешки и структура от код.

Първо, инсталирайте библиотеката:

pip install requests

Пример: Създаване на нова виртуална машина (LXC контейнер)

Този скрипт ще създаде нов LXC контейнер с минимални настройки.

#!/usr/bin/env python3

import requests
import json

# Конфигурация
pm_url = "https://pve1:8006/api2/json"
pm_user = "root@pam"
pm_token_name = "ansible" # Име на токена
pm_token_secret = "your-secret-token-uuid" # Секретната част на токена

# Игнориране на SSL предупрежденията (само за тестване!)
requests.packages.urllib3.disable_warnings()

# Функция за извършване на заявки
def make_proxmox_request(method, path, data=None):
    url = f"{pm_url}{path}"
    headers = {'Authorization': f'PVEAPIToken={pm_user}!{pm_token_name}={pm_token_secret}'}
    
    response = requests.request(method, url, headers=headers, verify=False, data=data)
    response.raise_for_status()  # Хвърля грешка ако статус кодът е 4xx/5xx
    return response.json()

# 1. Намиране на нода
cluster_status = make_proxmox_request('GET', '/cluster/status')
node_name = next(item for item in cluster_status['data'] if item['type'] == 'node')['name']
print(f"Използвам нод: {node_name}")

# 2. Създаване на LXC контейнер
new_vm_data = {
    "vmid": 200,           # Уникален ID
    "ostemplate": "local:vztmpl/ubuntu-22.04-standard_22.04-1_amd64.tar.zst", # Трябва да съществува
    "storage": "local-lvm",
    "memory": 1024,        # 1GB RAM
    "cores": 1,            # 1 ядро
    "password": "secure_password_123", # Парола за root
    "hostname": "my-new-container.example.com"
}

create_response = make_proxmox_request('POST', f'/nodes/{node_name}/lxc', data=new_vm_data)
print("Контейнерът е създаден успешно!")
print(f"Отговор: {create_response}")

Обяснение на Python кода:

  • Използваме токен за удостоверяване, който е по-сигурен. Заглавието Authorization се попълва по специфичен за Proxmox начин.
  • make_proxmox_request е наша помощна функция, която се грижи за досадните детайли като добавянето на headers и проверката за грешки.
  • Първо намираме името на един от нодовете в клъстъра.
  • След това изпращаме POST заявка с JSON данни, описващи новия контейнер.

Практически идеи за автоматизация: Отдалечете ръцете си от клавиатурата

Сега, след като знаете основите, ето няколко реални примера как да ги приложите:

1. Автоматично създаване на VM от шаблон:

  • Клонирайте "златна" VM образ (template), конфигурирайте мрежови настройки и пуснете я.
  • Полза: Моментално предоставяне на нови сървъри за разработчици.

2. Динамично скалиране:

  • Скрипт, който следи натоварването (чрез API) и автоматично добавя/премахва ресурси (CPU, RAM) към VM.
  • Полза: Подобрена производителност и оптимизирани разходи.

3. Интелигентна система за бекъпи:

  • Скрипт, който взима бекъпи само на променените VM (чрез проверка на ctime или backup флагове), качва ги във външно хранилище и изпраща имейл с резултат.
  • Полза: Надеждна и безгрижна стратегия за възстановяване при повреда.

4. "Самоизчистване" на клъстъра:

  • Скрипт, който автоматично изтрива стари, неизползвани VM-та, които са маркирани със специфичен таг.
  • Полза: Поддържане на чистота в инфраструктурата.

Proxmox API скриптове на Python

#!/usr/bin/env python3
"""
Proxmox API Скриптове
Изисква: pip install proxmoxer requests
"""

from proxmoxer import ProxmoxAPI
import getpass

# =============================================================================
# КОНФИГУРАЦИЯ - Промени тези стойности според твоята среда
# =============================================================================
PROXMOX_HOST = 'proxmox.example.com'
PROXMOX_USER = 'root@pam'
# За продукция използвай API Token вместо парола

def connect_proxmox():
    """Свързване към Proxmox API"""
    password = getpass.getpass(f"Парола за {PROXMOX_USER}: ")
    proxmox = ProxmoxAPI(
        PROXMOX_HOST,
        user=PROXMOX_USER,
        password=password,
        verify_ssl=False
    )
    return proxmox


# =============================================================================
# СКРИПТ 1: Листване на всички виртуални машини и контейнери
# =============================================================================
def list_all_vms(proxmox):
    """Показва всички VM и контейнери с техния статус"""
    print("\n" + "="*70)
    print("ВИРТУАЛНИ МАШИНИ И КОНТЕЙНЕРИ")
    print("="*70)
    
    for node in proxmox.nodes.get():
        node_name = node['node']
        print(f"\n📦 Node: {node_name}")
        print("-" * 70)
        
        # QEMU VMs
        for vm in proxmox.nodes(node_name).qemu.get():
            status = "🟢" if vm['status'] == 'running' else "🔴"
            print(f"  {status} VM {vm['vmid']}: {vm['name']:<30} | {vm['status']:<10} | RAM: {vm.get('mem', 0)//1024//1024}MB")
        
        # LXC Контейнери
        for ct in proxmox.nodes(node_name).lxc.get():
            status = "🟢" if ct['status'] == 'running' else "🔴"
            print(f"  {status} CT {ct['vmid']}: {ct['name']:<30} | {ct['status']:<10} | RAM: {ct.get('mem', 0)//1024//1024}MB")


# =============================================================================
# СКРИПТ 2: Резервно копие на конкретна VM/контейнер
# =============================================================================
def backup_vm(proxmox, node, vmid, storage='local'):
    """Създава backup на VM или контейнер"""
    print(f"\n🔄 Създаване на backup за VM/CT {vmid} на node {node}...")
    
    try:
        # Проверка дали е VM или контейнер
        try:
            vm_type = 'qemu'
            proxmox.nodes(node).qemu(vmid).status.current.get()
        except:
            vm_type = 'lxc'
        
        # Стартиране на backup задача
        if vm_type == 'qemu':
            task = proxmox.nodes(node).qemu(vmid).backup.post(
                storage=storage,
                mode='snapshot',
                compress='zstd'
            )
        else:
            task = proxmox.nodes(node).lxc(vmid).backup.post(
                storage=storage,
                mode='snapshot',
                compress='zstd'
            )
        
        print(f"✅ Backup задача стартирана: {task}")
        return task
    
    except Exception as e:
        print(f"❌ Грешка при backup: {e}")
        return None


# =============================================================================
# СКРИПТ 3: Масово стартиране/спиране на VM-ове
# =============================================================================
def bulk_vm_operation(proxmox, node, vmids, operation='start'):
    """
    Масова операция върху множество VM/контейнери
    operation: 'start', 'stop', 'shutdown', 'reboot'
    """
    print(f"\n⚡ Изпълнение на '{operation}' за {len(vmids)} машини...")
    
    results = {'success': [], 'failed': []}
    
    for vmid in vmids:
        try:
            # Опит за QEMU VM
            try:
                vm = proxmox.nodes(node).qemu(vmid)
                vm_type = 'VM'
            except:
                vm = proxmox.nodes(node).lxc(vmid)
                vm_type = 'CT'
            
            # Изпълнение на операцията
            if operation == 'start':
                vm.status.start.post()
            elif operation == 'stop':
                vm.status.stop.post()
            elif operation == 'shutdown':
                vm.status.shutdown.post()
            elif operation == 'reboot':
                vm.status.reboot.post()
            
            print(f"  ✅ {vm_type} {vmid}: {operation} успешно")
            results['success'].append(vmid)
            
        except Exception as e:
            print(f"  ❌ {vmid}: Грешка - {e}")
            results['failed'].append(vmid)
    
    print(f"\n📊 Резултат: {len(results['success'])} успешни, {len(results['failed'])} неуспешни")
    return results


# =============================================================================
# СКРИПТ 4: Клониране на VM
# =============================================================================
def clone_vm(proxmox, node, source_vmid, new_vmid, new_name, full_clone=True):
    """Клонира съществуваща VM"""
    print(f"\n🔄 Клониране на VM {source_vmid} → {new_vmid} ({new_name})...")
    
    try:
        task = proxmox.nodes(node).qemu(source_vmid).clone.post(
            newid=new_vmid,
            name=new_name,
            full=1 if full_clone else 0
        )
        print(f"✅ Клониране стартирано: {task}")
        return task
    
    except Exception as e:
        print(f"❌ Грешка при клониране: {e}")
        return None


# =============================================================================
# СКРИПТ 5: Мониторинг на ресурси
# =============================================================================
def monitor_resources(proxmox):
    """Показва използването на ресурси по nodes"""
    print("\n" + "="*70)
    print("МОНИТОРИНГ НА РЕСУРСИ")
    print("="*70)
    
    for node in proxmox.nodes.get():
        node_name = node['node']
        status = proxmox.nodes(node_name).status.get()
        
        cpu_usage = status['cpu'] * 100
        mem_used = status['memory']['used'] / 1024**3
        mem_total = status['memory']['total'] / 1024**3
        mem_percent = (status['memory']['used'] / status['memory']['total']) * 100
        
        print(f"\n🖥️  Node: {node_name}")
        print(f"  CPU: {cpu_usage:.1f}%")
        print(f"  RAM: {mem_used:.1f}GB / {mem_total:.1f}GB ({mem_percent:.1f}%)")
        print(f"  Uptime: {status['uptime']//86400} дни")


# =============================================================================
# СКРИПТ 6: Създаване на snapshot
# =============================================================================
def create_snapshot(proxmox, node, vmid, snapshot_name, description=""):
    """Създава snapshot на VM"""
    print(f"\n📸 Създаване на snapshot '{snapshot_name}' за VM {vmid}...")
    
    try:
        task = proxmox.nodes(node).qemu(vmid).snapshot.post(
            snapname=snapshot_name,
            description=description
        )
        print(f"✅ Snapshot създаден успешно")
        return task
    
    except Exception as e:
        print(f"❌ Грешка при създаване на snapshot: {e}")
        return None


# =============================================================================
# ГЛАВНА ФУНКЦИЯ - ПРИМЕРИ ЗА ИЗПОЛЗВАНЕ
# =============================================================================
def main():
    """Примери за използване на скриптовете"""
    
    # Свързване към Proxmox
    proxmox = connect_proxmox()
    print("✅ Успешно свързване към Proxmox API")
    
    # ПРИМЕР 1: Листване на всички VM
    list_all_vms(proxmox)
    
    # ПРИМЕР 2: Мониторинг на ресурси
    monitor_resources(proxmox)
    
    # ПРИМЕР 3: Backup на конкретна VM (размести коментара за да използваш)
    # backup_vm(proxmox, node='pve', vmid=100, storage='local')
    
    # ПРИМЕР 4: Масово стартиране на VM-ове
    # bulk_vm_operation(proxmox, node='pve', vmids=[100, 101, 102], operation='start')
    
    # ПРИМЕР 5: Клониране на VM
    # clone_vm(proxmox, node='pve', source_vmid=100, new_vmid=110, new_name='clone-vm')
    
    # ПРИМЕР 6: Създаване на snapshot
    # create_snapshot(proxmox, node='pve', vmid=100, snapshot_name='before-update', description='Преди обновяване')


if __name__ == "__main__":
    main()

Това е колекция от 6 полезни Proxmox API скриптове на Python. Ето какво включват:

📋 Основни функции:

  1. Листване на VM и контейнери – показва всички машини с техния статус
  2. Резервно копие – автоматичен backup на VM/контейнер
  3. Масови операции – едновременно start/stop/reboot на множество машини
  4. Клониране – бързо копиране на VM
  5. Мониторинг – преглед на използването на CPU/RAM
  6. Snapshots – създаване на моментни снимки

🚀 Как да използваш:

  1. Инсталирай библиотеката:
pip install proxmoxer requests

Редактирай PROXMOX_HOST и PROXMOX_USER в началото Стартирай скрипта:

python proxmox_scripts.py

  1. Размести коментарите на примерите в main() функцията за да активираш конкретни операции

💡 Съвет за сигурност: За продукционна среда е по-добре да използваш API Token вместо парола. Можеш да го създадеш от Datacenter → Permissions → API Tokens в Proxmox интерфейса.

Съвети от практика и най-добри практики

  1. Винаги използвайте API Token вместо пароли. Токените са по-сигурни и могат да бъдат отзвани, без да се променя паролата на потребителя.
  2. Четете официалната документация на API-то! Намерете я в https://[ВАШИЯ_PVE_NODE]:8006/pve-docs/api-viewer/. Тя е вашето най-добро ръководство и винаги е актуална.
  3. Не пренебрегвайте сигурността. В реална среда винаги използвайте валидни SSL сертификати. Не оставяйте токени или пароли в скриптовете директно. Използвайте системи за управление на тайни като vault или поне системни environment променливи.
  4. Тествайте върху не-продукционна система. Правенето на опити в production среда е най-бързия начин към инцидент.
  5. Започнете с малко. Автоматизирайте една проста задача. Вижте че работи. После поемете към следващата. Натрупването на малки победи води до голяма промяна.

Заключение

Автоматизацията с Proxmox API не е магия, запазена за гурута. Тя е практически умение, което всеки системен администратор може и трябва да усвои. Като започнете с прости bash скриптове и постепенно преминете към по-сложни решения на Python, вие не просто спестявате време. Вие създавате по-стабилна, възпроизводима и динамична инфраструктура.

Така че отворете вашия текстов редактор, прочетете документацията и дайте на вашия Proxmox клъстър нова команда. Ще се изненадате колко бързо той ще започне да ви слуша.

Федя Серафиев

Федя Серафиев

Федя Серафиев e собственик на уебсайта urocibg.eu. Той намира удовлетворение в това да помага на хората да решават и най-сложните технически проблеми. Сегашната му цел е да пише лесни за следване статии, така че подобни проблеми изобщо да не възникват.

Благодарим ви за прочитането на статията! Ако намерихте информацията за полезна, можете да дарите посредством бутоните по-долу:

Подобни статии