Proxmox’u web arayüzünden yönetmek başlangıç için yeterli olabilir, ama onlarca VM ve konteyner yönetir hale geldiğinizde tıkladığınız her buton size zaman kaybettirmeye başlar. İşte tam bu noktada Proxmox’un sunduğu RESTful API devreye giriyor. Altyapınızı kodla yönetmek, tekrar eden görevleri otomatize etmek ve kendi özel araçlarınızı geliştirmek için ihtiyacınız olan her şey bu API’da mevcut.
Bu yazıda sıfırdan başlayıp gerçek dünya senaryolarına kadar uzanan pratik Proxmox API kullanımını ele alacağız. Bash scriptlerinden Python’a, basit sorgulardan karmaşık otomasyona kadar her şeyi göreceksiniz.
Proxmox API’ye Giriş ve Kimlik Doğrulama
Proxmox API’si varsayılan olarak https://PROXMOX_IP:8006/api2/json adresinde çalışır. Her istek için kimlik doğrulaması gereklidir ve bunun iki yolu vardır.
Ticket tabanlı kimlik doğrulama geçici bir oturum tokeni üretir. Her 2 saatte bir yenilenmesi gerekir ancak hızlı scriptler için uygundur.
API Token kullanımı ise üretim ortamları için önerilen yöntemdir. Kullanıcıya bağlı uzun ömürlü tokenlar oluşturabilir, yetki kısıtlaması yapabilirsiniz.
Önce ticket tabanlı kimlik doğrulama ile başlayalım:
#!/bin/bash
PROXMOX_HOST="192.168.1.10"
PROXMOX_PORT="8006"
USERNAME="root@pam"
PASSWORD="sifreniz"
# Ticket al
RESPONSE=$(curl -s -k -X POST
"https://${PROXMOX_HOST}:${PROXMOX_PORT}/api2/json/access/ticket"
-d "username=${USERNAME}&password=${PASSWORD}")
# Token ve CSRF değerlerini çıkar
TICKET=$(echo $RESPONSE | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['data']['ticket'])")
CSRF=$(echo $RESPONSE | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['data']['CSRFPreventionToken'])")
echo "Ticket: $TICKET"
echo "CSRF: $CSRF"
# Bu değerleri sonraki isteklerde kullan
curl -s -k
-H "Cookie: PVEAuthCookie=${TICKET}"
-H "CSRFPreventionToken: ${CSRF}"
"https://${PROXMOX_HOST}:${PROXMOX_PORT}/api2/json/nodes"
API Token ile çalışmak daha temizdir. Önce Proxmox arayüzünden veya CLI’dan token oluşturun:
# Proxmox sunucusunda çalıştırın
pveum user token add root@pam otomasyon-token --privsep=0
# Çıktıda token değeri görünecek, bunu kaydedin
# Örnek: root@pam!otomasyon-token=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Token ile istek atmak çok daha basittir:
#!/bin/bash
PROXMOX_HOST="192.168.1.10"
API_TOKEN="root@pam!otomasyon-token=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
curl -s -k
-H "Authorization: PVEAPIToken=${API_TOKEN}"
"https://${PROXMOX_HOST}:8006/api2/json/nodes" | python3 -m json.tool
Senaryo 1: Tüm Cluster Durumunu İzleme
Sabah işe geldiğinizde cluster’ın genel sağlığını hızlıca görmek istiyorsunuz. Bunun için tüm node’ları, üzerindeki VM’leri ve kaynak kullanımını tek seferde çeken bir script yazalım:
#!/bin/bash
PROXMOX_HOST="192.168.1.10"
API_TOKEN="root@pam!monitor-token=TOKEN_DEGERINIZ"
BASE_URL="https://${PROXMOX_HOST}:8006/api2/json"
api_get() {
curl -s -k
-H "Authorization: PVEAPIToken=${API_TOKEN}"
"${BASE_URL}/$1"
}
echo "=== PROXMOX CLUSTER DURUM RAPORU ==="
echo "Tarih: $(date)"
echo ""
# Tüm node'ları listele
NODES=$(api_get "nodes" | python3 -c "
import sys, json
data = json.load(sys.stdin)['data']
for node in data:
cpu_pct = round(node['cpu'] * 100, 2)
mem_used = round(node['mem'] / 1024 / 1024 / 1024, 2)
mem_total = round(node['maxmem'] / 1024 / 1024 / 1024, 2)
status = node['status']
print(f"Node: {node['node']} | Durum: {status} | CPU: {cpu_pct}% | RAM: {mem_used}/{mem_total} GB")
")
echo "$NODES"
echo ""
# Her node'daki VM sayısını al
for node in $(api_get "nodes" | python3 -c "import sys,json; [print(n['node']) for n in json.load(sys.stdin)['data']]"); do
VM_COUNT=$(api_get "nodes/${node}/qemu" | python3 -c "import sys,json; d=json.load(sys.stdin)['data']; print(len(d))")
CT_COUNT=$(api_get "nodes/${node}/lxc" | python3 -c "import sys,json; d=json.load(sys.stdin)['data']; print(len(d))")
echo " $node: $VM_COUNT VM, $CT_COUNT Konteyner"
done
Bu scripti cron’a ekleyip her sabah mail atmasını sağlayabilirsiniz:
# crontab -e
0 8 * * 1-5 /opt/scripts/cluster-rapor.sh | mail -s "Proxmox Sabah Raporu" [email protected]
Senaryo 2: Toplu VM Snapshot Alma
Güncelleme gecesi geldi ve 20 VM’in snapshot’ını tek tek almak istemiyorsunuz. Bu script tüm çalışan VM’lerin snapshot’ını alır ve işlem takibini yapar:
#!/bin/bash
PROXMOX_HOST="192.168.1.10"
API_TOKEN="root@pam!backup-token=TOKEN_DEGERINIZ"
BASE_URL="https://${PROXMOX_HOST}:8006/api2/json"
SNAPSHOT_NAME="guncelleme-oncesi-$(date +%Y%m%d)"
NODE="pve01"
echo "Snapshot alınıyor: ${SNAPSHOT_NAME}"
echo "----------------------------------------"
# Çalışan tüm VM'leri al
VMIDS=$(curl -s -k
-H "Authorization: PVEAPIToken=${API_TOKEN}"
"${BASE_URL}/nodes/${NODE}/qemu" |
python3 -c "
import sys, json
vms = json.load(sys.stdin)['data']
for vm in vms:
if vm['status'] == 'running':
print(vm['vmid'])
")
BASARILI=0
BASARISIZ=0
for VMID in $VMIDS; do
echo -n "VM ${VMID} snapshot alınıyor... "
TASK=$(curl -s -k -X POST
-H "Authorization: PVEAPIToken=${API_TOKEN}"
"${BASE_URL}/nodes/${NODE}/qemu/${VMID}/snapshot"
-d "snapname=${SNAPSHOT_NAME}&description=Otomatik snapshot - guncelleme oncesi")
TASKID=$(echo $TASK | python3 -c "import sys,json; print(json.load(sys.stdin)['data'])" 2>/dev/null)
if [ -n "$TASKID" ]; then
# Task tamamlanana kadar bekle
for i in $(seq 1 30); do
sleep 2
STATUS=$(curl -s -k
-H "Authorization: PVEAPIToken=${API_TOKEN}"
"${BASE_URL}/nodes/${NODE}/tasks/${TASKID}/status" |
python3 -c "import sys,json; print(json.load(sys.stdin)['data']['status'])")
if [ "$STATUS" = "stopped" ]; then
echo "TAMAM"
BASARILI=$((BASARILI + 1))
break
fi
done
else
echo "HATA"
BASARISIZ=$((BASARISIZ + 1))
fi
done
echo "----------------------------------------"
echo "Sonuc: $BASARILI basarili, $BASARISIZ basarisiz"
Senaryo 3: Python ile VM Provisioning Otomasyonu
Bash scriptleri basit işler için yeterli ama daha karmaşık senaryolarda Python çok daha güçlüdür. proxmoxer kütüphanesi ile şablon klonlama ve konfigürasyon işlemlerini otomatikleştiren bir script yazalım:
pip3 install proxmoxer requests
#!/usr/bin/env python3
"""
Proxmox VM Provisioning Scripti
Kullanim: python3 provision.py --name web-server-01 --cores 4 --memory 8192
"""
import argparse
import time
from proxmoxer import ProxmoxAPI
# Konfigürasyon
PROXMOX_HOST = "192.168.1.10"
API_TOKEN_ID = "root@pam!provision-token"
API_TOKEN_SECRET = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
NODE = "pve01"
TEMPLATE_VMID = 9000 # Ubuntu 22.04 template VM ID
STORAGE = "local-lvm"
NETWORK_BRIDGE = "vmbr0"
def create_vm(name, cores, memory, disk_size, start_after=True):
"""
Şablondan yeni VM oluştur ve yapılandır
"""
prox = ProxmoxAPI(
PROXMOX_HOST,
user=API_TOKEN_ID,
token_value=API_TOKEN_SECRET,
verify_ssl=False
)
# Boş bir VMID bul
vmid = prox.cluster.nextid.get()
print(f"Yeni VM ID: {vmid}")
# Şablonu klonla
print(f"Şablon {TEMPLATE_VMID} klonlanıyor -> {name} ({vmid})")
task = prox.nodes(NODE).qemu(TEMPLATE_VMID).clone.post(
newid=vmid,
name=name,
full=1,
storage=STORAGE
)
# Klonlama tamamlanana kadar bekle
wait_for_task(prox, NODE, task)
print("Klonlama tamamlandi.")
# VM konfigürasyonunu güncelle
print(f"Konfigürasyon guncelleniyor: {cores} core, {memory}MB RAM")
prox.nodes(NODE).qemu(vmid).config.put(
cores=cores,
memory=memory,
net0=f"virtio,bridge={NETWORK_BRIDGE}",
ipconfig0=f"ip=dhcp",
ciuser="sysadmin",
cipassword="GucluSifre123!",
sshkeys="ssh-rsa AAAAB3... [email protected]"
)
# Disk boyutunu ayarla
if disk_size:
print(f"Disk boyutu ayarlaniyor: +{disk_size}G")
prox.nodes(NODE).qemu(vmid).resize.put(
disk="scsi0",
size=f"+{disk_size}G"
)
# VM'i başlat
if start_after:
print("VM baslatiliyor...")
prox.nodes(NODE).qemu(vmid).status.start.post()
print(f"VM {name} ({vmid}) baslatildi!")
return vmid
def wait_for_task(prox, node, task_id, timeout=300):
"""Task tamamlanana kadar bekle"""
elapsed = 0
while elapsed < timeout:
status = prox.nodes(node).tasks(task_id).status.get()
if status['status'] == 'stopped':
if status.get('exitstatus') == 'OK':
return True
else:
raise Exception(f"Task basarisiz: {status.get('exitstatus')}")
time.sleep(3)
elapsed += 3
print(".", end="", flush=True)
raise TimeoutError("Task zaman asimina ugradi")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Proxmox VM Provisioning")
parser.add_argument("--name", required=True, help="VM adi")
parser.add_argument("--cores", type=int, default=2, help="CPU core sayisi")
parser.add_argument("--memory", type=int, default=4096, help="RAM (MB)")
parser.add_argument("--disk", type=int, default=20, help="Ekstra disk (GB)")
parser.add_argument("--no-start", action="store_true", help="Olusturunca baslatma")
args = parser.parse_args()
vmid = create_vm(
name=args.name,
cores=args.cores,
memory=args.memory,
disk_size=args.disk,
start_after=not args.no_start
)
print(f"nVM basariyla olusturuldu! VMID: {vmid}")
Bu scripti kullanmak son derece basit:
# Yeni web sunucusu oluştur
python3 provision.py --name web-server-01 --cores 4 --memory 8192 --disk 50
# DB sunucusu oluştur, henüz başlatma
python3 provision.py --name db-master-01 --cores 8 --memory 16384 --disk 100 --no-start
Senaryo 4: Kaynak Kullanım Alarmı
Disk dolmadan, RAM bitmeden haberdar olmak istiyorsunuz. Bu script her 5 dakikada çalışıp eşiği aşan VM’leri Slack veya mail ile bildirir:
#!/bin/bash
PROXMOX_HOST="192.168.1.10"
API_TOKEN="root@pam!monitor-token=TOKEN"
BASE_URL="https://${PROXMOX_HOST}:8006/api2/json"
SLACK_WEBHOOK="https://hooks.slack.com/services/XXXXX/YYYYY/ZZZZZ"
CPU_ESIK=85
RAM_ESIK=90
send_alert() {
local message="$1"
echo "[ALARM] $message"
# Slack bildirimi
curl -s -X POST "$SLACK_WEBHOOK"
-H "Content-Type: application/json"
-d "{"text":":warning: *Proxmox Alarm*n${message}"}" > /dev/null
}
for NODE in $(curl -s -k
-H "Authorization: PVEAPIToken=${API_TOKEN}"
"${BASE_URL}/nodes" | python3 -c "import sys,json; [print(n['node']) for n in json.load(sys.stdin)['data']]"); do
# Çalışan VM'lerin kaynak kullanımını kontrol et
curl -s -k
-H "Authorization: PVEAPIToken=${API_TOKEN}"
"${BASE_URL}/nodes/${NODE}/qemu" |
python3 -c "
import sys, json
data = json.load(sys.stdin)['data']
for vm in data:
if vm['status'] != 'running':
continue
cpu_pct = round(vm.get('cpu', 0) * 100, 1)
mem_pct = round(vm.get('mem', 0) / max(vm.get('maxmem', 1), 1) * 100, 1)
vmid = vm['vmid']
name = vm.get('name', 'unknown')
if cpu_pct > ${CPU_ESIK}:
print(f'CPU|{name} ({vmid}) CPU kullanimi yuksek: {cpu_pct}%')
if mem_pct > ${RAM_ESIK}:
print(f'RAM|{name} ({vmid}) RAM kullanimi yuksek: {mem_pct}%')
" | while IFS='|' read -r tip mesaj; do
send_alert "$mesaj"
done
done
Senaryo 5: LXC Konteyner Fabrikası
Geliştirici ekibiniz her sprint başında test ortamı istiyor. Bu script istek üzerine LXC konteynerleri oluşturur, yapılandırır ve SSH erişimini hazırlar:
#!/bin/bash
PROXMOX_HOST="192.168.1.10"
API_TOKEN="root@pam!dev-token=TOKEN"
BASE_URL="https://${PROXMOX_HOST}:8006/api2/json"
NODE="pve01"
STORAGE="local-lvm"
TEMPLATE="local:vztmpl/ubuntu-22.04-standard_22.04-1_amd64.tar.zst"
create_lxc() {
local DEV_ADI="$1"
local PROJE="$2"
# Sonraki boş ID al
CTID=$(curl -s -k
-H "Authorization: PVEAPIToken=${API_TOKEN}"
"${BASE_URL}/cluster/nextid" | python3 -c "import sys,json; print(json.load(sys.stdin)['data'])")
echo "Konteyner olusturuluyor: ${PROJE}-${DEV_ADI} (CT ID: ${CTID})"
# LXC oluştur
TASK=$(curl -s -k -X POST
-H "Authorization: PVEAPIToken=${API_TOKEN}"
"${BASE_URL}/nodes/${NODE}/lxc"
-d "vmid=${CTID}"
-d "hostname=${PROJE}-${DEV_ADI}"
-d "ostemplate=${TEMPLATE}"
-d "storage=${STORAGE}"
-d "rootfs=${STORAGE}:10"
-d "cores=2"
-d "memory=2048"
-d "swap=512"
-d "net0=name=eth0,bridge=vmbr0,ip=dhcp"
-d "password=DevPass123!"
-d "ssh-public-keys=ssh-rsa AAAA... [email protected]"
-d "unprivileged=1"
-d "start=1" | python3 -c "import sys,json; print(json.load(sys.stdin)['data'])")
echo "Task ID: $TASK - Tamamlanmasi bekleniyor..."
# Tamamlanmasını bekle
for i in $(seq 1 20); do
sleep 3
STATUS=$(curl -s -k
-H "Authorization: PVEAPIToken=${API_TOKEN}"
"${BASE_URL}/nodes/${NODE}/tasks/${TASK}/status" |
python3 -c "import sys,json; print(json.load(sys.stdin)['data']['status'])")
if [ "$STATUS" = "stopped" ]; then
echo "Konteyner hazir! CT ID: ${CTID}"
echo "SSH: ssh root@$(get_ct_ip $CTID)"
break
fi
echo -n "."
done
}
# Kullanim
# ./lxc-fabrika.sh ahmet-yilmaz backend-api
create_lxc "$1" "$2"
Senaryo 6: Otomatik Yedek Dogrulama
Yedek aldınız ama çalışıyor mu? Bu script son yedekleri listeler ve boyut/tarih kontrolü yaparak sonuçları raporlar:
#!/usr/bin/env python3
from proxmoxer import ProxmoxAPI
from datetime import datetime, timedelta
import sys
prox = ProxmoxAPI(
"192.168.1.10",
user="root@pam!backup-token",
token_value="TOKEN_DEGERINIZ",
verify_ssl=False
)
STORAGE = "backup-storage"
MAX_YEDEK_YASI_SAAT = 26 # 26 saatten eski yedek varsa uyar
print("=== YEDEK DOGRULAMA RAPORU ===")
print(f"Tarih: {datetime.now().strftime('%Y-%m-%d %H:%M')}")
print("")
uyarilar = []
for node in prox.nodes.get():
node_name = node['node']
try:
yedekler = prox.nodes(node_name).storage(STORAGE).content.get(
content="backup"
)
except Exception as e:
print(f"[HATA] {node_name} yedekleri okunamadi: {e}")
continue
# VM bazinda son yedekleri grupla
vm_yedekleri = {}
for yedek in yedekler:
vmid = yedek.get('vmid', 'unknown')
ctime = yedek.get('ctime', 0)
if vmid not in vm_yedekleri or ctime > vm_yedekleri[vmid]['ctime']:
vm_yedekleri[vmid] = yedek
print(f"Node: {node_name} ({len(vm_yedekleri)} VM yedegi)")
for vmid, yedek in sorted(vm_yedekleri.items()):
yedek_tarihi = datetime.fromtimestamp(yedek['ctime'])
yas_saat = (datetime.now() - yedek_tarihi).total_seconds() / 3600
boyut_gb = round(yedek['size'] / 1024 / 1024 / 1024, 2)
durum = "OK" if yas_saat <= MAX_YEDEK_YASI_SAAT else "UYARI"
print(f" VM {vmid}: {boyut_gb} GB | {yedek_tarihi.strftime('%Y-%m-%d %H:%M')} | {durum}")
if durum == "UYARI":
uyarilar.append(f"VM {vmid} yedegi eski: {round(yas_saat, 1)} saat once alinmis")
print("")
if uyarilar:
print("=== UYARILAR ===")
for u in uyarilar:
print(f"[!] {u}")
sys.exit(1)
else:
print("Tum yedekler guncel. Sorun yok.")
sys.exit(0)
API Kullanımında Dikkat Edilmesi Gerekenler
Proxmox API ile çalışırken karşılaşabileceğiniz birkaç önemli nokta var:
Rate Limiting: Proxmox API’si çok hızlı istek atılırsa bağlantıları reddedebilir. Döngü içindeki istekler arasına kısa bir sleep ekleyin.
SSL Sertifikası: Test ortamlarında self-signed sertifika kullanılıyorsa -k flag’i veya Python’da verify_ssl=False kullanın. Üretimde kesinlikle geçerli sertifika kullanın.
Token Yetkileri: Her token için en az yetkiyi tanımlayın. Monitoring tokeni sadece VM.Monitor ve Datastore.Audit yetkisine sahip olmalı, provisioning tokeni ise VM.Allocate ve VM.Clone yetkilerine ihtiyaç duyar.
Task Takibi: API’deki uzun süren işlemler (klonlama, backup gibi) asenkron çalışır ve bir task ID döner. İşlemin tamamlandığını anlamak için task durumunu sorgulamak zorundasınız, aksi halde yarım kalmış işlemlerle uğraşırsınız.
Hata Yönetimi: API 4xx veya 5xx dönüyorsa detaylı hata mesajını parse etmeyi ihmal etmeyin. Proxmox genellikle çok açıklayıcı hata mesajları döner.
Loglama: Otomasyon scriptlerinizin ne yaptığını mutlaka loglayın. Bir şeyler ters gittiğinde kim ne zaman hangi VM’i sildi diye bakabiliyor olmanız hayat kurtarır.
Sonuç
Proxmox API’si, altyapı yönetimini gerçek anlamda “infrastructure as code” seviyesine taşımanızı sağlar. Sabahları cluster durumunu kontrol etmekten yeni geliştirici ortamı hazırlamaya, yedek doğrulamadan toplu snapshot almaya kadar pek çok tekrar eden görevi devre dışı bırakabilirsiniz.
Başlamak için karmaşık bir proje kurmanıza gerek yok. Önce mevcut süreçlerinizde en çok zaman harcadığınız tekrar eden görevi belirleyin ve o iş için küçük bir script yazın. İlk birkaç başarılı otomasyon, sizi daha büyük şeyler yazmaya teşvik edecektir.
Üretim ortamında token tabanlı kimlik doğrulamayı, minimum yetki prensibini ve kapsamlı loglamayı asla atlamamalısınız. API güçlü bir araçtır ve yanlış kullanıldığında VM silmek de dahil olmak üzere geri alınamaz işlemler yapabilir. Scriptlerinizi önce test ortamında deneyin, kademeli olarak üretime taşıyın.