一、开篇:为什么我们需要用API来管理存储?

想象一下,你管理着一整个机房的超聚变服务器。每次需要给服务器配置存储,比如创建一个RAID阵列来保护数据,或者增加几块硬盘扩展存储空间,你都得跑到机房,或者通过远程控制台,点开那个图形化的管理界面,点点这个,选选那个。

如果只有一两台服务器,这倒没什么。但如果要管理几十、上百台,而且需要在凌晨业务低峰期批量操作,这种手动方式就变得非常低效且容易出错了。这时候,API的价值就体现出来了。

Redfish,你可以把它理解为一套专门为服务器管理设计的“通用语言”。它基于我们熟悉的RESTful API和JSON格式,让我们能够用写代码的方式,去完成所有在图形界面上能做的操作。今天,我们就来聊聊如何通过Redfish API,对超聚变服务器的存储部分进行“编程式”管理,实现RAID阵列的创建和磁盘组的管理。全程使用Python,因为它的语法清晰,非常适合演示。

二、准备工作:认识你的服务器和工具

在开始写代码之前,我们需要做一些准备工作。

首先,你得知道你的超聚变服务器的BMC(基板管理控制器)的IP地址、用户名和密码。这些信息通常由你的系统管理员提供。BMC就是服务器上那个负责带外管理的小心脏,Redfish API就运行在它上面。

其次,我们需要一个能发送HTTP请求的工具。在Python里,requests库是我们的不二之选。它简单又好用。

# 技术栈:Python + requests
# 安装命令:pip install requests

import requests
import json
import time
from requests.auth import HTTPBasicAuth

# 1. 定义连接信息
# 请将以下信息替换为你自己服务器的实际信息
BMC_IP = “192.168.1.100”      # 你的服务器BMC IP
USERNAME = “admin”            # BMC用户名
PASSWORD = “your_strong_password” # BMC密码
BASE_URL = f“https://{BMC_IP}” # Redfish API的根地址

# 2. 创建一个会话,并禁用SSL证书警告(仅用于测试环境,生产环境请使用有效证书)
# 注意:在生产环境中,务必验证证书以确保安全!
session = requests.Session()
session.auth = HTTPBasicAuth(USERNAME, PASSWORD)
session.verify = False  # 跳过SSL验证,仅用于演示
requests.packages.urllib3.disable_warnings() # 关闭警告

# 3. 获取Redfish服务的根目录,验证连接
try:
    response = session.get(f“{BASE_URL}/redfish/v1/”)
    response.raise_for_status() # 如果状态码不是200,会抛出异常
    service_root = response.json()
    print(“连接成功!Redfish服务版本:”, service_root.get(‘RedfishVersion’))
except requests.exceptions.RequestException as e:
    print(f“连接失败:{e}”)
    exit(1)

这段代码是我们的“敲门砖”。它建立了与服务器BMC的通信,并确认Redfish服务是可用的。记住,生产环境一定要处理SSL证书,这里跳过只是为了演示方便。

三、核心操作:探索存储系统与磁盘

在创建RAID之前,我们得先知道服务器里有什么“存货”。Redfish通过一个清晰的资源模型来展示硬件信息。

# 技术栈:Python + requests
# 续接上面的代码

# 4. 找到存储系统的链接
# 通常,存储信息位于 `Systems` 和 `Storage` 集合下
systems_url = f“{BASE_URL}/redfish/v1/Systems”
systems_response = session.get(systems_url)
systems_data = systems_response.json()

# 假设我们取第一个系统(对于单机服务器通常只有一个)
system_member_url = systems_data[‘Members’][0][‘@odata.id’]
system_response = session.get(f“{BASE_URL}{system_member_url}”)
system_data = system_response.json()

# 获取该系统的存储集合链接
storage_url = system_data.get(‘Storage’, {}).get(‘@odata.id’)
if not storage_url:
    print(“未找到存储系统信息。”)
    exit(1)

# 5. 列出所有存储控制器和磁盘
storage_response = session.get(f“{BASE_URL}{storage_url}”)
storage_data = storage_response.json()

print(“\n=== 发现存储控制器 ===")
for controller_member in storage_data.get(‘Members’, []):
    controller_url = controller_member[‘@odata.id’]
    controller_response = session.get(f“{BASE_URL}{controller_url}”)
    controller_data = controller_response.json()
    controller_id = controller_url.split(‘/’)[-1]
    print(f“控制器ID: {controller_id}”)
    print(f“  名称: {controller_data.get(‘Name’)}”)
    print(f“  型号: {controller_data.get(‘Model’)}”)

    # 获取该控制器下的磁盘驱动器(物理硬盘)信息
    drives_url = controller_data.get(‘Drives’)
    if drives_url:
        drives_response = session.get(f“{BASE_URL}{drives_url[‘@odata.id’]}")
        drives_data = drives_response.json()
        print(f“  连接的物理磁盘:”)
        for drive_member in drives_data.get(‘Members’, []):
            drive_url = drive_member[‘@odata.id’]
            drive_response = session.get(f“{BASE_URL}{drive_url}”)
            drive_info = drive_response.json()
            drive_name = drive_info.get(‘Name’, ‘N/A’)
            drive_capacity = drive_info.get(‘CapacityBytes’, 0)
            # 将字节转换为GB
            capacity_gb = round(drive_capacity / (1024**3), 2) if drive_capacity else 0
            print(f“    - {drive_name}: {capacity_gb} GB”)
    print(“-” * 30)

运行这段代码,你就能在控制台看到服务器里所有RAID卡(存储控制器)和每块硬盘的详细信息,比如容量、型号。这是我们后续操作的基础。

四、实战演练:创建RAID阵列(磁盘组)

现在进入正题。假设我们手头有几块空闲硬盘,想用它们创建一个RAID5阵列,用来提供数据冗余保护。

在Redfish中,创建RAID阵列(在超聚变或其他支持Redfish的服务器中,常被称为Volume或逻辑磁盘)通常需要向存储控制器的Volumes集合发送一个POST请求。请求体里要详细说明我们的配置意图。

# 技术栈:Python + requests
# 续接上面的代码,假设我们已经找到了目标控制器,其URL存储在 `target_controller_url` 变量中

# 6. 创建RAID5阵列(逻辑卷)
# 假设我们选择控制器 ‘1’,并且有3块空闲磁盘(ID为 32:0, 32:1, 32:2)用于创建RAID5
target_controller_url = f“{BASE_URL}/redfish/v1/Systems/1/Storage/RAID.Integrated.1-1” # 示例URL,需根据实际情况修改

# 首先,确认控制器的操作链接
controller_response = session.get(target_controller_url)
controller_data = controller_response.json()
volumes_collection_url = controller_data.get(‘Volumes’, {}).get(‘@odata.id’)

if not volumes_collection_url:
    print(“该控制器不支持创建逻辑卷或URL未找到。”)
    exit(1)

# 准备创建逻辑卷的请求体
create_volume_payload = {
    “@odata.type”: “#Volume.v1_6_0.Volume”, # 根据Redfish Schema版本调整
    “Name”: “My_Data_RAID5”,  # 给你的阵列起个名字
    “RAIDType”: “RAID5”,       # 阵列类型,可选 RAID0, RAID1, RAID5, RAID6, RAID10等
    “CapacityBytes”: 0,        # 设置为0表示使用所有选定磁盘的全部可用容量
    “OptimumIOSizeBytes”: 65536, # 最佳IO大小,通常64KB是个好选择
    “Drives”: [                # 指定用于创建阵列的物理磁盘列表
        {
            “@odata.id”: f“{target_controller_url}/Drives/Disk.32:0” # 磁盘的完整Redfish ID
        },
        {
            “@odata.id”: f“{target_controller_url}/Drives/Disk.32:1”
        },
        {
            “@odata.id”: f“{target_controller_url}/Drives/Disk.32:2”
        }
    ]
}

print(f“\n正在向 {volumes_collection_url} 发送创建请求...”)
try:
    # 发送POST请求创建逻辑卷
    create_response = session.post(
        f“{BASE_URL}{volumes_collection_url}”,
        json=create_volume_payload,
        headers={‘Content-Type’: ‘application/json’}
    )

    if create_response.status_code in [200, 201, 202, 204]:
        # 202 Accepted表示任务已接受,通常意味着后台开始初始化
        print(“创建请求已接受!服务器正在后台初始化RAID阵列。”)
        # 如果返回了任务(Task)链接,可以跟踪进度
        task_location = create_response.headers.get(‘Location’)
        if task_location:
            print(f“可以访问此链接跟踪任务进度:{task_location}”)
            # 这里可以编写轮询任务状态的代码,直到完成
    else:
        print(f“创建失败!状态码:{create_response.status_code}”)
        print(“响应内容:”, create_response.text)
except Exception as e:
    print(f“请求过程中发生错误:{e}”)

这段代码的核心是构造一个JSON请求。RAIDType指定了阵列级别,Drives数组列出了要用的具体硬盘。发送后,服务器通常会返回一个“任务”(Task)链接,你可以通过不断查询这个链接来了解初始化进度(比如“正在初始化,完成15%”)。

五、管理磁盘组:查询与删除

创建了阵列,我们自然也需要能查看和清理它们。

# 技术栈:Python + requests
# 续接上面的代码

# 7. 查询已创建的逻辑卷(磁盘组)
print(“\n=== 查询现有逻辑卷 ===")
volumes_response = session.get(f“{BASE_URL}{volumes_collection_url}”)
volumes_data = volumes_response.json()

for volume_member in volumes_data.get(‘Members’, []):
    volume_url = volume_member[‘@odata.id’]
    volume_response = session.get(f“{BASE_URL}{volume_url}”)
    volume_info = volume_response.json()
    vol_id = volume_url.split(‘/’)[-1]
    print(f“逻辑卷ID: {vol_id}”)
    print(f“  名称: {volume_info.get(‘Name’)}”)
    print(f“  RAID类型: {volume_info.get(‘RAIDType’)}”)
    print(f“  容量: {round(volume_info.get(‘CapacityBytes’,0) / (1024**3), 2)} GB”)
    print(f“  操作状态: {volume_info.get(‘Status’, {}).get(‘State’)}”)
    print(“-” * 20)

# 8. 删除一个逻辑卷(谨慎操作!数据会丢失!)
# 假设我们要删除上面创建的名为 ‘My_Data_RAID5’ 的卷
volume_to_delete = None
for volume_member in volumes_data.get(‘Members’, []):
    volume_url = volume_member[‘@odata.id’]
    volume_response = session.get(f“{BASE_URL}{volume_url}”)
    volume_info = volume_response.json()
    if volume_info.get(‘Name’) == “My_Data_RAID5”:
        volume_to_delete = volume_url
        break

if volume_to_delete:
    confirm = input(f“\n确认要删除逻辑卷 ‘My_Data_RAID5’ 吗?此操作不可逆!(输入 ‘yes’ 确认): “)
    if confirm.lower() == ‘yes’:
        delete_response = session.delete(f“{BASE_URL}{volume_to_delete}”)
        if delete_response.status_code in [200, 202, 204]:
            print(“删除请求已接受。”)
        else:
            print(f“删除失败。状态码:{delete_response.status_code}”)
    else:
        print(“操作已取消。”)
else:
    print(“未找到要删除的逻辑卷。”)

删除操作非常简单,就是一个DELETE请求,但危险性极高,所以代码里加了确认环节。在实际的自动化脚本中,这个确认环节可能会被一个明确的配置参数所替代。

六、深入理解:技术细节与注意事项

应用场景:

  1. 大规模自动化部署:在数据中心,结合Ansible、Terraform等工具,实现新服务器上架后存储的自动配置。
  2. 运维自动化:定时巡检存储健康状态,自动替换故障硬盘并触发重建。
  3. 云平台与虚拟化集成:为私有云平台提供底层硬件存储资源的按需分配和管理能力。
  4. 灾难恢复演练:通过脚本快速重建测试环境的存储结构。

技术优缺点:

  • 优点
    • 标准化:Redfish是DMTF主导的开放标准,避免了不同厂商私有接口的锁定。
    • 自动化友好:基于HTTP/JSON,极易与任何编程语言和运维工具集成。
    • 功能强大:覆盖了服务器管理的方方面面,存储配置只是其中之一。
    • 带外管理:不依赖主机操作系统,即使系统宕机也能管理硬件。
  • 缺点
    • 学习曲线:需要理解Redfish的资源模型和Schema,初期有一定学习成本。
    • 厂商实现差异:虽然标准统一,但不同厂商、不同型号的服务器在细节(如支持的RAID级别、属性名)上可能有细微差别,需要查阅具体产品的文档。
    • 异步操作:像创建RAID这种耗时操作,返回的是任务链接,需要额外编写代码来轮询状态,增加了逻辑复杂度。

注意事项:

  1. 安全第一:务必在HTTPS下使用,并验证证书。管理账号使用强密码,并遵循最小权限原则。
  2. 充分测试:任何删除或重构存储的操作,务必在测试环境中充分验证后再在生产环境执行。误操作会导致数据丢失。
  3. 查阅官方文档:超聚变或其他服务器厂商都会提供其Redfish API的详细指南和Schema文件,这是最权威的参考资料,里面会列出所有可用的端点、参数和枚举值。
  4. 错误处理:生产代码必须包含完善的错误处理(网络超时、认证失败、API错误码解析等)和日志记录。
  5. 任务状态跟踪:对于长时间运行的操作,一定要实现任务状态的跟踪机制,避免脚本误以为操作已完成。

七、总结

通过这篇指南,我们走完了使用Redfish API管理超聚变服务器存储的核心流程:从建立连接、发现硬件,到创建RAID阵列,再到查询和删除。我们使用了Python和requests库,将图形界面上的点击操作,转化为了清晰、可重复、可集成的代码。

这种方式将我们从繁琐的重复性手动操作中解放出来,为构建现代化、自动化的数据中心运维体系打下了坚实的基础。虽然初期需要投入一些时间理解Redfish模型和编写脚本,但长远来看,其带来的效率提升和可靠性保障是巨大的。下次当你需要面对一堆服务器时,不妨试试用代码和它们“对话”。