DIABOLIKSS
RehberlerDell iDRAC Redfish API ile Sunucu Otomasyonu
DELL ALTYAPISI

Dell iDRAC Redfish API ileSunucu Otomasyonu

5 Haziran 2026 30 dk okuma İleri Seviye Redfish · Python · Ansible · curl

Dell iDRAC Redfish REST API, DMTF standardına uygun vendor-agnostic bir protokollerdir. Bu rehber; Python SDK, curl ve Ansible ile PowerEdge sunucularını tamamen programatik olarak yönetmeyi, firmware güncelleme pipeline'ları oluşturmayı ve toplu otomasyon scriptleri yazmayı eksiksiz kod örnekleriyle açıklamaktadır.

01

Redfish Mimarisi ve iDRAC Endpoint'leri

DMTF Redfish, veri merkezi donanımlarını yönetmek için tasarlanmış, REST tabanlı, JSON formatında bir API standardıdır. Dell iDRAC9, Redfish 1.15+ standardına uyumlu tam bir implementasyon sunar. Her Redfish kaynağı, hiyerarşik bir URI yapısıyla erişilebilir ve kendini açıklayan (self-describing) JSON şemaları içerir.

iDRAC Redfish API'nin kök URI'si /redfish/v1'dir. Bu endpoint, sistemde mevcut tüm kaynakları (Systems, Chassis, Managers, UpdateService vb.) listeler. Her kaynak kendi altında bağlantılı alt kaynakları barındırır; bu yapı Hypermedia as the Engine of Application State (HATEOAS) prensibine dayanır.

Kaynak URI Açıklama
Servis Kökü/redfish/v1Tüm kaynakların giriş noktası
Sistem/redfish/v1/Systems/System.Embedded.1Host sistem bilgisi, güç, boot
BIOS/redfish/v1/Systems/System.Embedded.1/BiosBIOS ayarları okuma/yazma
Depolama/redfish/v1/Systems/System.Embedded.1/StorageRAID, disk envanteri
Yöneticiler/redfish/v1/Managers/iDRAC.Embedded.1iDRAC yapılandırması
Güncelleme/redfish/v1/UpdateServiceFirmware yükleme ve envanter
Olay Servisi/redfish/v1/EventServiceOlay abonelikleri
Görev Servisi/redfish/v1/TaskService/TasksArka plan görevleri
# Redfish Service Root keşfi curl -sk -u root:PASSWORD \ https://10.10.1.50/redfish/v1 \ | python3 -m json.tool # Tüm mevcut koleksiyonları listele curl -sk -u root:PASSWORD \ https://10.10.1.50/redfish/v1 \ | python3 -c " import sys, json data = json.load(sys.stdin) for k, v in data.items(): if isinstance(v, dict) and '@odata.id' in v: print(f'{k}: {v[\"@odata.id\"]}') "
ℹ️
iDRAC Redfish API'si varsayılan olarak TLS 1.2+ kullanır. Python requests kütüphanesiyle verify=False kullanıldığında InsecureRequestWarning uyarısı alırsınız. Üretim scriptlerinde kurumsal CA sertifikasını verify="/path/to/ca.crt" ile belirtin.
02

Python ile Redfish İstemcisi

Dell, python-redfish-library ve iDRAC-Redfish-Scripting adlı iki resmi Python kütüphanesi sağlar. Bunların yanı sıra DMTF'nin redfish kütüphanesi de kullanılabilir. Pratik otomasyon scriptleri için requests kütüphanesi en esnek yaklaşımı sunar; çünkü iDRAC'a özgü Dell OEM extension'larına doğrudan erişim sağlar.

Yeniden kullanılabilir bir Redfish istemci sınıfı oluşturmak, birden fazla sunucu üzerinde aynı operasyonları çalıştırmayı kolaylaştırır. Aşağıda temel operasyonları kapsayan bir Python sınıfı verilmiştir:

# redfish_client.py — Dell iDRAC Redfish istemci sınıfı import requests import json import time import urllib3 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) class DellRedfishClient: def __init__(self, host, username, password, verify=False): self.base_url = f"https://{host}" self.auth = (username, password) self.verify = verify self.session_token = None self.session_uri = None def create_session(self): """Oturum tabanlı kimlik doğrulama""" resp = requests.post( f"{self.base_url}/redfish/v1/Sessions", json={"UserName": self.auth[0], "Password": self.auth[1]}, verify=self.verify ) resp.raise_for_status() self.session_token = resp.headers["X-Auth-Token"] self.session_uri = resp.json()["@odata.id"] return self.session_token def get(self, uri): headers = {"X-Auth-Token": self.session_token} if self.session_token else {} resp = requests.get( f"{self.base_url}{uri}", auth=None if self.session_token else self.auth, headers=headers, verify=self.verify ) resp.raise_for_status() return resp.json() def patch(self, uri, payload): headers = { "Content-Type": "application/json", "X-Auth-Token": self.session_token } resp = requests.patch( f"{self.base_url}{uri}", json=payload, headers=headers, verify=self.verify ) resp.raise_for_status() return resp def post(self, uri, payload=None): headers = { "Content-Type": "application/json", "X-Auth-Token": self.session_token } resp = requests.post( f"{self.base_url}{uri}", json=payload, headers=headers, verify=self.verify ) return resp def wait_for_task(self, task_uri, timeout=600, poll_interval=10): """Görev tamamlanana kadar bekle""" start = time.time() while time.time() - start < timeout: task = self.get(task_uri) status = task.get("TaskState") pct = task.get("PercentComplete", 0) print(f"\r [{pct:3}%] {status}", end="", flush=True) if status in ["Completed", "Exception", "Killed"]: print() return task time.sleep(poll_interval) raise TimeoutError(f"Görev {timeout}s içinde tamamlanmadı") def close_session(self): if self.session_uri: requests.delete( f"{self.base_url}{self.session_uri}", headers={"X-Auth-Token": self.session_token}, verify=self.verify )
# Kullanım örneği from redfish_client import DellRedfishClient client = DellRedfishClient("10.10.1.50", "root", "PASSWORD") client.create_session() # Sistem bilgisi system = client.get("/redfish/v1/Systems/System.Embedded.1") print(f"Model: {system['Model']}") print(f"Güç: {system['PowerState']}") print(f"Seri No: {system['SKU']}") # Firmware envanteri fw_inv = client.get("/redfish/v1/UpdateService/FirmwareInventory") for member in fw_inv["Members"]: fw = client.get(member["@odata.id"]) print(f" {fw['Name']}: {fw['Version']}") client.close_session()
03

curl ile Temel Operasyonlar

curl, CI/CD pipeline'larında ve bash scriptlerinde Redfish API çağrıları için yaygın olarak tercih edilir. Aşağıda en sık kullanılan iDRAC operasyonları için hazır curl komutları verilmiştir. Bu komutlar doğrudan script içine gömülebilir veya test amaçlı terminal'den çalıştırılabilir.

# Ortam değişkenlerini ayarla (scripte ekle) IDRAC_HOST="10.10.1.50" IDRAC_USER="root" IDRAC_PASS="PASSWORD" BASE="https://$IDRAC_HOST" AUTH="-u $IDRAC_USER:$IDRAC_PASS" HEADERS="-H 'Content-Type: application/json'" # Sistem özeti curl -sk $AUTH "$BASE/redfish/v1/Systems/System.Embedded.1" \ | python3 -c " import sys, json; d=json.load(sys.stdin) print('Model:', d.get('Model')) print('Güç:', d.get('PowerState')) print('İşlemci:', d.get('ProcessorSummary',{}).get('Count'), 'x', d.get('ProcessorSummary',{}).get('Model','')) print('RAM:', d.get('MemorySummary',{}).get('TotalSystemMemoryGiB'), 'GiB') " # Chassis termal bilgisi (sıcaklık ve fanlar) curl -sk $AUTH "$BASE/redfish/v1/Chassis/System.Embedded.1/Thermal" \ | python3 -c " import sys, json; d=json.load(sys.stdin) print('=== Sıcaklıklar ===') for t in d.get('Temperatures', []): print(f\" {t['Name']}: {t.get('ReadingCelsius','N/A')} C\") print('=== Fanlar ===') for f in d.get('Fans', []): print(f\" {f['FanName']}: {f.get('Reading','N/A')} RPM\") "
# Güç yönetimi operasyonları # Güvenli yeniden başlatma (graceful restart) curl -sk $AUTH -X POST \ -H "Content-Type: application/json" \ -d '{"ResetType":"GracefulRestart"}' \ "$BASE/redfish/v1/Systems/System.Embedded.1/Actions/ComputerSystem.Reset" # Zorla kapatma curl -sk $AUTH -X POST \ -H "Content-Type: application/json" \ -d '{"ResetType":"ForceOff"}' \ "$BASE/redfish/v1/Systems/System.Embedded.1/Actions/ComputerSystem.Reset" # iDRAC sıfırlama (iDRAC yeniden başlatma, host etkilenmez) curl -sk $AUTH -X POST \ -H "Content-Type: application/json" \ -d '{"ResetType":"GracefulRestart"}' \ "$BASE/redfish/v1/Managers/iDRAC.Embedded.1/Actions/Manager.Reset"
# Depolama envanteri curl -sk $AUTH "$BASE/redfish/v1/Systems/System.Embedded.1/Storage" \ | python3 -c " import sys, json, requests, urllib3 urllib3.disable_warnings() d=json.load(sys.stdin) for m in d.get('Members', []): print('Kontrolör:', m['@odata.id'].split('/')[-1]) " # Disk listesi (ilk kontrolör) curl -sk $AUTH \ "$BASE/redfish/v1/Systems/System.Embedded.1/Storage/RAID.Integrated.1-1/Drives" \ | python3 -m json.tool | grep -E '"@odata.id"|"Name"'
04

Firmware Güncelleme Otomasyonu

Redfish üzerinden firmware güncelleme, MultipartUpload endpoint'ine DUP dosyasını yükleyerek veya uzak bir HTTP/CIFS/NFS sunucusundaki DUP dosyasına referans vererek yapılır. Güncelleme işlemi arka planda bir task olarak çalışır; task tamamlanana kadar poll edilmesi gerekir.

Toplu güncellemeler için önce firmware envanteri alınır, mevcut versiyonlar hedef versiyonlarla karşılaştırılır ve güncelleme gerektiren bileşenler için sıralı veya paralel güncelleme görevleri oluşturulur. BIOS ve iDRAC güncellemeleri yeniden başlatma gerektirdiğinden bunlar ayrı bir gruba alınmalıdır.

# firmware_updater.py — Tek sunucu firmware güncelleme import requests, os, sys, time, json import urllib3 urllib3.disable_warnings() def upload_firmware(host, user, password, dup_file): base = f"https://{host}" auth = (user, password) print(f"Yükleniyor: {os.path.basename(dup_file)}") with open(dup_file, "rb") as f: resp = requests.post( f"{base}/redfish/v1/UpdateService/MultipartUpload", files={"file": (os.path.basename(dup_file), f, "application/octet-stream")}, data={"UpdateParameters": json.dumps({ "Targets": [], "@Redfish.OperationApplyTime": "OnReset" })}, auth=auth, verify=False ) if resp.status_code not in [200, 202]: print(f"HATA: {resp.status_code} - {resp.text}") return None task_uri = resp.headers.get("Location", "").replace(base, "") print(f"Görev oluşturuldu: {task_uri}") return task_uri def wait_task(host, user, password, task_uri, timeout=600): base = f"https://{host}" auth = (user, password) start = time.time() while time.time() - start < timeout: r = requests.get(f"{base}{task_uri}", auth=auth, verify=False) t = r.json() state = t.get("TaskState", "Unknown") pct = t.get("PercentComplete", 0) print(f"\r [{pct:3d}%] {state}", end="", flush=True) if state in ["Completed", "Exception"]: print() return state == "Completed" time.sleep(15) return False # Kullanım HOST = "10.10.1.50" task = upload_firmware(HOST, "root", "PASSWORD", "/tmp/BIOS_XYR9K_WN64_2.20.0.EXE") if task: success = wait_task(HOST, "root", "PASSWORD", task) print("Güncelleme başarılı!" if success else "Güncelleme başarısız!")
⚠️
Dikkat: @Redfish.OperationApplyTime değeri OnReset olarak ayarlandığında firmware, sunucu bir sonraki yeniden başlatmada uygulanır. Immediate kullanıldığında ise bazı bileşenler (örn. NIC firmware) anlık güncelleme sırasında kısa süreli bağlantı keser.
05

BIOS Yapılandırma Otomasyonu

Redfish üzerinden BIOS ayarları okuma ve yazma işlemi, /redfish/v1/Systems/System.Embedded.1/Bios endpoint'i üzerinden gerçekleştirilir. BIOS ayarları pending settings mekanizmasıyla çalışır: değişiklikler önce Bios/Settings endpoint'ine yazılır, ardından sunucu yeniden başlatıldığında Lifecycle Controller tarafından uygulanır.

# Mevcut BIOS ayarlarını oku curl -sk -u root:PASSWORD \ "https://10.10.1.50/redfish/v1/Systems/System.Embedded.1/Bios" \ | python3 -c " import sys, json d = json.load(sys.stdin) attrs = d.get('Attributes', {}) # Sanallaştırma ile ilgili ayarları filtrele virt_keys = [k for k in attrs if 'virt' in k.lower() or 'proc' in k.lower()] for k in sorted(virt_keys): print(f'{k}: {attrs[k]}') "
# BIOS ayarlarını değiştir (PATCH to Settings) curl -sk -u root:PASSWORD \ -X PATCH \ -H "Content-Type: application/json" \ -d '{ "Attributes": { "ProcVirtualization": "Enabled", "SysProfile": "PerfOptimized", "LogicalProc": "Enabled", "NodeInterleave": "Disabled", "ProcCStates": "Disabled", "MemTest": "Disabled", "BootMode": "Uefi" } }' \ "https://10.10.1.50/redfish/v1/Systems/System.Embedded.1/Bios/Settings" \ | python3 -m json.tool # Değişiklikler için maintenance window job oluştur curl -sk -u root:PASSWORD \ -X POST \ -H "Content-Type: application/json" \ -d '{ "TargetSettingsURI": "/redfish/v1/Systems/System.Embedded.1/Bios/Settings", "Oem": { "Dell": { "JobType": "BIOSConfiguration" } } }' \ "https://10.10.1.50/redfish/v1/Managers/iDRAC.Embedded.1/Jobs" \ | python3 -m json.tool
# Python ile çok sunuculu BIOS standardizasyonu from redfish_client import DellRedfishClient STANDARD_BIOS = { "ProcVirtualization": "Enabled", "SysProfile": "PerfOptimized", "LogicalProc": "Enabled", "BootMode": "Uefi", "NodeInterleave": "Disabled", } SERVERS = ["10.10.1.50", "10.10.1.51", "10.10.1.52"] for server in SERVERS: print(f"\n=== {server} ===") try: c = DellRedfishClient(server, "root", "PASSWORD") c.create_session() # Mevcut ayarları kontrol et bios = c.get("/redfish/v1/Systems/System.Embedded.1/Bios") attrs = bios.get("Attributes", {}) drift = {k: v for k, v in STANDARD_BIOS.items() if attrs.get(k) != v} if drift: print(f" Drift tespit edildi: {drift}") c.patch("/redfish/v1/Systems/System.Embedded.1/Bios/Settings", {"Attributes": drift}) print(f" Değişiklikler uygulandı (yeniden başlatma bekleniyor)") else: print(" BIOS uyumlu, değişiklik gerekmedi") c.close_session() except Exception as e: print(f" HATA: {e}")
06

Ansible ile iDRAC Yönetimi

Dell, dellemc.openmanage Ansible koleksiyonunu resmi olarak destekler. Bu koleksiyon, iDRAC Redfish ve RACADM üzerinden sunucu yönetimini Ansible playbook'larına entegre eder. 80'den fazla modül içerir: firmware güncelleme, BIOS yapılandırma, RAID kurulumu, kullanıcı yönetimi ve daha fazlası.

# dellemc.openmanage koleksiyonunu kur ansible-galaxy collection install dellemc.openmanage # Gereksinimler pip3 install omsdk requests # inventory.yml — iDRAC envanteri cat > /tmp/dell_inventory.yml <<'EOF' all: children: idrac_hosts: hosts: r760-01: ansible_host: 10.10.1.50 idrac_user: root idrac_password: "PASSWORD" r760-02: ansible_host: 10.10.1.51 idrac_user: root idrac_password: "PASSWORD" EOF
# playbook_firmware_update.yml cat > /tmp/playbook_firmware_update.yml <<'EOF' --- - name: Dell iDRAC Firmware Güncelleme hosts: idrac_hosts gather_facts: no tasks: - name: Mevcut firmware versiyonlarını al dellemc.openmanage.idrac_firmware_info: idrac_ip: "{{ ansible_host }}" idrac_user: "{{ idrac_user }}" idrac_password: "{{ idrac_password }}" validate_certs: false register: fw_info - name: Firmware versiyonlarını göster debug: msg: "{{ fw_info.firmware_info.ComponentType }}" - name: BIOS firmware güncelle (catalog bazlı) dellemc.openmanage.idrac_firmware: idrac_ip: "{{ ansible_host }}" idrac_user: "{{ idrac_user }}" idrac_password: "{{ idrac_password }}" validate_certs: false share_name: "10.10.1.200:/firmware-catalog" share_type: NFS catalog_file_name: "Catalog.xml" apply_update: true reboot: false job_wait: true register: update_result - name: Güncelleme sonucunu raporla debug: msg: "Güncelleme durumu: {{ update_result.update_status }}" EOF ansible-playbook -i /tmp/dell_inventory.yml /tmp/playbook_firmware_update.yml
# playbook_bios_config.yml — BIOS standardizasyonu cat > /tmp/playbook_bios_config.yml <<'EOF' --- - name: Dell PowerEdge BIOS Standardizasyonu hosts: idrac_hosts gather_facts: no vars: bios_attributes: ProcVirtualization: "Enabled" SysProfile: "PerfOptimized" LogicalProc: "Enabled" NodeInterleave: "Disabled" BootMode: "Uefi" tasks: - name: BIOS özniteliklerini uygula dellemc.openmanage.idrac_bios: idrac_ip: "{{ ansible_host }}" idrac_user: "{{ idrac_user }}" idrac_password: "{{ idrac_password }}" validate_certs: false attributes: "{{ bios_attributes }}" register: bios_result - name: Sonucu göster debug: msg: "{{ bios_result.msg }}" EOF ansible-playbook -i /tmp/dell_inventory.yml /tmp/playbook_bios_config.yml
07

Çok Sunuculu Toplu İşlem Pipeline'ı

Onlarca veya yüzlerce sunucuda aynı operasyonu gerçekleştirmek için eşzamanlı (concurrent) bir Python pipeline oluşturmak hem zaman hem de iş yükü açısından büyük avantaj sağlar. concurrent.futures.ThreadPoolExecutor kullanılarak paralel Redfish çağrıları yapılabilir.

# bulk_operations.py — Paralel çok sunuculu operasyonlar import concurrent.futures import requests, json, urllib3, csv from datetime import datetime urllib3.disable_warnings() def get_server_info(server): """Tek sunucu için bilgi toplama""" host, user, password = server["ip"], server["user"], server["password"] base = f"https://{host}" auth = (user, password) try: r = requests.get( f"{base}/redfish/v1/Systems/System.Embedded.1", auth=auth, verify=False, timeout=30 ) d = r.json() # iDRAC versiyonu mgr = requests.get( f"{base}/redfish/v1/Managers/iDRAC.Embedded.1", auth=auth, verify=False, timeout=30 ).json() return { "ip": host, "hostname": d.get("HostName", "N/A"), "model": d.get("Model", "N/A"), "serial": d.get("SKU", "N/A"), "power": d.get("PowerState", "N/A"), "health": d.get("Status", {}).get("Health", "N/A"), "idrac_fw": mgr.get("FirmwareVersion", "N/A"), "error": None } except Exception as e: return {"ip": host, "error": str(e)} # Sunucu listesini CSV'den oku SERVERS = [] with open("/tmp/servers.csv") as f: for row in csv.DictReader(f): # ip,user,password SERVERS.append(row) print(f"Toplam {len(SERVERS)} sunucu taranıyor...") results = [] with concurrent.futures.ThreadPoolExecutor(max_workers=20) as executor: futures = {executor.submit(get_server_info, s): s for s in SERVERS} for future in concurrent.futures.as_completed(futures): result = future.result() results.append(result) status = "✓" if not result.get("error") else "✗" print(f" {status} {result['ip']}: {result.get('model','HATA')}") # Sonuçları CSV'ye kaydet output_file = f"/tmp/server_inventory_{datetime.now().strftime('%Y%m%d_%H%M')}.csv" with open(output_file, "w", newline="") as f: writer = csv.DictWriter(f, fieldnames=results[0].keys()) writer.writeheader() writer.writerows(results) print(f"\nRapor kaydedildi: {output_file}")
08

Hata Yönetimi ve İzleme

Otomasyon scriptlerinde hata yönetimi, özellikle toplu operasyonlarda kritik önem taşır. Ağ zaman aşımları, kimlik doğrulama hataları, iDRAC meşgul durumları ve görev başarısızlıkları için uygun retry mekanizmaları ve loglama eklenmelidir.

Uzun süren görevlerin (firmware güncelleme, BIOS yapılandırma) durumu düzenli aralıklarla poll edilmeli ve sonuçlar hem terminal'e hem de bir log dosyasına yazılmalıdır. Kritik hatalar için e-posta veya Slack webhook bildirimleri eklenebilir.

# Exponential backoff ile retry mekanizması import time, functools, logging logging.basicConfig( level=logging.INFO, format='%(asctime)s [%(levelname)s] %(message)s', handlers=[ logging.FileHandler('/tmp/idrac_automation.log'), logging.StreamHandler() ] ) def retry(max_attempts=3, delay=5, backoff=2, exceptions=(Exception,)): def decorator(func): @functools.wraps(func) def wrapper(*args, **kwargs): attempt = 1 wait = delay while attempt <= max_attempts: try: return func(*args, **kwargs) except exceptions as e: if attempt == max_attempts: logging.error(f"Son deneme başarısız: {func.__name__} - {e}") raise logging.warning(f"Deneme {attempt} başarısız, {wait}s sonra tekrar: {e}") time.sleep(wait) wait *= backoff attempt += 1 return wrapper return decorator # Kullanım: decorator ile API çağrısını güvenli hale getir @retry(max_attempts=3, delay=10, backoff=2) def safe_get_system_info(client, server_ip): return client.get("/redfish/v1/Systems/System.Embedded.1")
# Webhook bildirimi (Slack veya Teams) import requests def notify_webhook(webhook_url, message, level="info"): color_map = { "info": "#007db8", "success": "#22c55e", "warning": "#f0a500", "error": "#ff6b35" } payload = { "attachments": [{ "color": color_map.get(level, "#007db8"), "text": message, "footer": "Dell iDRAC Automation" }] } requests.post(webhook_url, json=payload, timeout=10) # Örnek kullanım SLACK_WEBHOOK = "https://hooks.slack.com/services/XXX/YYY/ZZZ" notify_webhook(SLACK_WEBHOOK, "10.10.1.50 - BIOS firmware güncelleme tamamlandı (v2.20.0)", "success")
  • Python Redfish istemci sınıfı oluşturuldu ve test edildi
  • Oturum yönetimi (token tabanlı) ve güvenli kapatma uygulandı
  • Firmware güncelleme pipeline'ı task polling ile tamamlandı
  • BIOS drift detection ve standart uygulama scripti hazırlandı
  • Ansible playbook'ları dellemc.openmanage ile test edildi
  • Toplu operasyonlar ThreadPoolExecutor ile paralel çalışıyor
  • Retry mekanizması ve merkezi loglama eklendi
  • Kritik hatalar için webhook bildirimleri yapılandırıldı