Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"@odata.context": "/redfish/v1/$metadata#Systems/Members/1/SmartStorage/ArrayControllers/Members/3/DiskDrives/Members/$entity",
"@odata.id": "/redfish/v1/Systems/1/SmartStorage/ArrayControllers/3/DiskDrives/4/",
"@odata.type": "#HpSmartStorageDiskDrive.1.3.0.HpSmartStorageDiskDrive",
"BlockSizeBytes": 512,
"CapacityGB": 600,
"CapacityLogicalBlocks": 1172123568,
"CapacityMiB": 572325,
"CarrierApplicationVersion": "11",
"CarrierAuthenticationStatus": "OK",
"CurrentTemperatureCelsius": 35,
"Description": "HP Smart Storage Disk Drive View",
"DiskDriveStatusReasons": [
"None"
],
"EncryptedDrive": false,
"FirmwareVersion": {
"Current": {
"VersionString": "HPD4"
}
},
"Id": "4",
"InterfaceSpeedMbps": 12000,
"InterfaceType": "SAS",
"Location": "1I:1:1",
"LocationFormat": "ControllerPort:Box:Bay",
"MaximumTemperatureCelsius": 48,
"MediaType": "HDD",
"Model": "EH0600JEDHE",
"Name": "HpSmartStorageDiskDrive",
"PowerOnHours": null,
"RotationalSpeedRpm": 15000,
"SSDEnduranceUtilizationPercentage": null,
"SerialNumber": "S7M0EG2D0000K60456LU",
"Status": {
"Health": "OK",
"State": "Enabled"
},
"Type": "HpSmartStorageDiskDrive.1.3.0",
"links": {
"self": {
"href": "/redfish/v1/Systems/1/SmartStorage/ArrayControllers/3/DiskDrives/4/"
}
}
}
59 changes: 48 additions & 11 deletions python/understack-workflows/tests/test_bmc_disk.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,41 +5,78 @@

from understack_workflows.bmc_disk import Disk

TESTED_DISK_PATH = "/redfish/v1/Systems/System.Embedded.1/Storage/RAID.SL.1-1/Drives/Disk.Bay.1:Enclosure.Internal.0-1:RAID.SL.1-1" # noqa: E501
DELL_TEST_DISK_PATH = "/redfish/v1/Systems/System.Embedded.1/Storage/RAID.SL.1-1/Drives/Disk.Bay.1:Enclosure.Internal.0-1:RAID.SL.1-1" # noqa: E501
HP_TEST_DISK_PATH = (
"/redfish/v1/Systems/1/SmartStorage/ArrayControllers/3/DiskDrives/4/"
)


@pytest.fixture
def mock_disk_data():
with open("tests/json_samples/bmc_chassis_info/bmc_disk.json") as f:
def mock_dell_disk_data():
with open("tests/json_samples/bmc_chassis_info/r7615_bmc_disk.json") as f:
return json.load(f)


@pytest.fixture
def mock_bmc(mock_disk_data, mocker: MockerFixture):
def mock_hp_disk_data():
with open("tests/json_samples/bmc_chassis_info/dl380_bmc_disk.json") as f:
return json.load(f)


@pytest.fixture
def mock_dell_bmc(mock_dell_disk_data, mocker: MockerFixture):
mock_bmc = mocker.Mock()
mock_bmc.get_manufacturer.return_value = "dell inc."
mock_bmc.redfish_request.return_value = mock_dell_disk_data
return mock_bmc


@pytest.fixture
def mock_hp_bmc(mock_hp_disk_data, mocker: MockerFixture):
mock_bmc = mocker.Mock()
mock_bmc.redfish_request.return_value = mock_disk_data
mock_bmc.get_manufacturer.return_value = "hpe"
mock_bmc.redfish_request.return_value = mock_hp_disk_data
return mock_bmc


def test_disk_from_path(mock_bmc):
disk = Disk.from_path(mock_bmc, TESTED_DISK_PATH)
def test_dell_disk_from_path(mock_dell_bmc):
disk = Disk.from_path(mock_dell_bmc, DELL_TEST_DISK_PATH)
assert isinstance(disk, Disk)


def test_disk_repr(mock_bmc):
disk = Disk.from_path(mock_bmc, TESTED_DISK_PATH)
def test_dell_disk_repr(mock_dell_bmc):
disk = Disk.from_path(mock_dell_bmc, DELL_TEST_DISK_PATH)
assert repr(disk) == disk.name


def test_disk_attributes(mock_bmc):
disk = Disk.from_path(mock_bmc, TESTED_DISK_PATH)
def test_dell_disk_attributes(mock_dell_bmc):
disk = Disk.from_path(mock_dell_bmc, DELL_TEST_DISK_PATH)
assert disk.media_type == "SSD"
assert disk.model == "MTFDDAK480TDS"
assert disk.name == "Solid State Disk 0:1:1"
assert disk.health == "OK"
assert disk.capacity_bytes == 479559942144


def test_hp_disk_from_path(mock_hp_bmc):
disk = Disk.from_path(mock_hp_bmc, HP_TEST_DISK_PATH)
assert isinstance(disk, Disk)


def test_hp_disk_repr(mock_hp_bmc):
disk = Disk.from_path(mock_hp_bmc, HP_TEST_DISK_PATH)
assert repr(disk) == disk.name


def test_hp_disk_attributes(mock_hp_bmc):
disk = Disk.from_path(mock_hp_bmc, HP_TEST_DISK_PATH)
assert disk.media_type == "HDD"
assert disk.model == "EH0600JEDHE"
assert disk.name == "1I:1:1"
assert disk.health == "OK"
assert disk.capacity_bytes == 600000000000


def test_disk_gb_conversion():
disk = Disk(
media_type="SSD",
Expand Down
4 changes: 4 additions & 0 deletions python/understack-workflows/understack_workflows/bmc.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ def get_manager_path(self):
_result = self.redfish_request("/redfish/v1/Managers/")
return _result["Members"][0]["@odata.id"].rstrip("/")

def get_manufacturer(self) -> str:
"""Read and return Manufacturer."""
return self.redfish_request(self.system_path)["Manufacturer"].lower()

def get_user_accounts(self, token: str | None = None) -> list[dict]:
"""A vendor agnostic approach to crawling the API for BMC accounts."""
path = self.base_path
Expand Down
54 changes: 43 additions & 11 deletions python/understack-workflows/understack_workflows/bmc_disk.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,31 +27,63 @@ def capacity_gb(self) -> int:
"""Capacity Math."""
return math.ceil(self.capacity_bytes / 10**9)

@staticmethod
def get_capacity_bytes(number) -> int:
"""Calculate capacity_bytes."""
return math.ceil(number * 10**9)

@staticmethod
def from_path(bmc: Bmc, path: str):
"""Disk path request."""
disk_data = bmc.redfish_request(path)

bmc_type = bmc.get_manufacturer()
if "dell" in bmc_type:
_bytes = disk_data["CapacityBytes"]
_name = disk_data["Name"]
else:
_bytes = Disk.get_capacity_bytes(disk_data["CapacityGB"])
_name = disk_data["Location"]
return Disk(
media_type=disk_data["MediaType"],
model=disk_data["Model"],
name=disk_data["Name"],
name=_name,
health=disk_data.get("Status", {}).get("Health", "Unknown"),
capacity_bytes=disk_data["CapacityBytes"],
capacity_bytes=_bytes,
)


def physical_disks(bmc: Bmc) -> list[Disk]:
"""Retrieve list of physical physical_disks."""
try:
storage_member_paths = [
member["@odata.id"]
for member in bmc.redfish_request(bmc.system_path + "/Storage")["Members"]
]
disks = [
bmc.redfish_request(drive_path)["Drives"]
for drive_path in storage_member_paths
]
bmc_type = bmc.get_manufacturer()
if "dell" in bmc_type:
path = "/Storage"
storage_member_paths = [
member["@odata.id"]
for member in bmc.redfish_request(bmc.system_path + path)["Members"]
]
disks = [
bmc.redfish_request(drive_path)["Drives"]
for drive_path in storage_member_paths
]
disk_paths = [disk for sublist in disks for disk in sublist]
disk_list = [
Disk.from_path(bmc, path=disk["@odata.id"]) for disk in disk_paths
]
else:
path = "/SmartStorage/ArrayControllers"
storage_controller_paths = [
member["@odata.id"]
for member in bmc.redfish_request(bmc.system_path + path)["Members"]
]
storage_member_paths = [
bmc.redfish_request(drive_path)["links"]["PhysicalDrives"]["href"]
for drive_path in storage_controller_paths
]
disks = [
bmc.redfish_request(drive_path)["Members"]
for drive_path in storage_member_paths
]
disk_paths = [disk for sublist in disks for disk in sublist]
disk_list = [Disk.from_path(bmc, path=disk["@odata.id"]) for disk in disk_paths]
logger.debug("Retrieved %d disks.", len(disk_list))
Expand Down
Loading