Add comprehensive PCIe device support to Sushy
Implement complete Redfish PCIeDevice v1.19.0 specification support including PCIeDevice and PCIeDeviceCollection resources embedded data support. - Add PCIeDevice resource with schema compliance - Support embedded PCIeDevices (Dell iDRAC pattern) - Add methods for device inspection - Comprehensive test coverage included onnboard devices too - Handle both standard and embedded PCIeDevices patterns Change-Id: I0326d5c2985e1b09828daa0f003b147f09628d3a Signed-off-by: Nidhi Rai <nidhi.rai94@gmail.com>
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Adds comprehensive PCIeDevice resource support implementing the complete
|
||||
Redfish PCIeDevice v1.19.0 specification. The new pcie_devices property
|
||||
on System objects provides access to PCIe device collections with support
|
||||
for both standard Redfish collections and embedded PCIeDevices (Dell iDRAC).
|
||||
|
||||
Features include full schema compliance, PCIe interface information and
|
||||
slot details.
|
189
sushy/resources/system/pcie_device.py
Normal file
189
sushy/resources/system/pcie_device.py
Normal file
@@ -0,0 +1,189 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
# This is referred from Redfish standard schema.
|
||||
# https://redfish.dmtf.org/schemas/v1/PCIeDevice.v1_19_0.json
|
||||
# Per DMTF DSP0268_2025.2 Section 6.96 PCIeDevice 1.19.0
|
||||
import logging
|
||||
|
||||
from sushy.resources import base
|
||||
from sushy.resources import common
|
||||
from sushy import utils
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class PCIeInterfaceField(base.CompositeField):
|
||||
"""PCIe interface information for the device."""
|
||||
|
||||
lanes_in_use = base.Field('LanesInUse', adapter=utils.int_or_none)
|
||||
"""The number of PCIe lanes in use by this device."""
|
||||
|
||||
max_lanes = base.Field('MaxLanes', adapter=utils.int_or_none)
|
||||
"""The number of PCIe lanes supported by this device."""
|
||||
|
||||
max_pcie_type = base.Field('MaxPCIeType')
|
||||
"""The highest version of the PCIe specification supported by this
|
||||
device."""
|
||||
pcie_type = base.Field('PCIeType')
|
||||
"""The version of the PCIe specification in use by this device."""
|
||||
|
||||
|
||||
class SlotField(base.CompositeField):
|
||||
"""Slot information for the PCIe device."""
|
||||
|
||||
lanes = base.Field('Lanes', adapter=utils.int_or_none)
|
||||
"""The number of PCIe lanes supported by this slot."""
|
||||
|
||||
location = base.Field('Location')
|
||||
"""The location of the PCIe slot."""
|
||||
|
||||
pcie_type = base.Field('PCIeType')
|
||||
"""The PCIe specification this slot supports."""
|
||||
|
||||
slot_type = base.Field('SlotType')
|
||||
"""The PCIe slot type."""
|
||||
|
||||
hot_pluggable = base.Field('HotPluggable', adapter=bool)
|
||||
"""An indication of whether this PCIe slot supports hotplug."""
|
||||
|
||||
lane_splitting = base.Field('LaneSplitting')
|
||||
"""The lane splitting strategy used in the PCIe slot."""
|
||||
|
||||
|
||||
class PCIeDevice(base.ResourceBase):
|
||||
"""Represents a PCIe device associated with a system."""
|
||||
|
||||
identity = base.Field('Id', required=True)
|
||||
"""The PCIe device identity string"""
|
||||
|
||||
name = base.Field('Name')
|
||||
"""The PCIe device name"""
|
||||
|
||||
description = base.Field('Description')
|
||||
"""The PCIe device description"""
|
||||
|
||||
manufacturer = base.Field('Manufacturer')
|
||||
"""The manufacturer of this PCIe device."""
|
||||
|
||||
model = base.Field('Model')
|
||||
"""The model number for the PCIe device."""
|
||||
|
||||
serial_number = base.Field('SerialNumber')
|
||||
"""The serial number for this PCIe device."""
|
||||
|
||||
part_number = base.Field('PartNumber')
|
||||
"""The part number for this PCIe device."""
|
||||
|
||||
sku = base.Field('SKU')
|
||||
"""The stock-keeping unit for this PCIe device."""
|
||||
|
||||
device_type = base.Field('DeviceType')
|
||||
"""The device type for this PCIe device."""
|
||||
|
||||
firmware_version = base.Field('FirmwareVersion')
|
||||
"""The version of firmware for this PCIe device."""
|
||||
|
||||
asset_tag = base.Field('AssetTag')
|
||||
"""The user-assigned asset tag for this PCIe device."""
|
||||
|
||||
status = common.StatusField('Status')
|
||||
"""The status and health of the resource and its subordinate resources."""
|
||||
|
||||
pcie_interface = PCIeInterfaceField('PCIeInterface')
|
||||
"""The PCIe interface details for this device."""
|
||||
|
||||
slot = SlotField('Slot')
|
||||
"""Information about the slot for this PCIe device."""
|
||||
|
||||
links = base.Field('Links')
|
||||
"""Links to related resources."""
|
||||
|
||||
|
||||
class PCIeDeviceCollection(base.ResourceCollectionBase):
|
||||
@property
|
||||
def _resource_type(self):
|
||||
return PCIeDevice
|
||||
|
||||
@property
|
||||
@utils.cache_it
|
||||
def device_count(self):
|
||||
"""The number of PCIe devices in the collection.
|
||||
|
||||
Returns the cached value until it (or its parent resource)
|
||||
is refreshed.
|
||||
"""
|
||||
return len(self.get_members())
|
||||
|
||||
def __init__(self, connector, path, redfish_version=None, registries=None,
|
||||
root=None, embedded_data=None):
|
||||
if path == "/empty":
|
||||
self._conn = connector
|
||||
self._path = path
|
||||
self._json = {'Members': []}
|
||||
self.redfish_version = redfish_version
|
||||
self._registries = registries
|
||||
self._root = root
|
||||
self._is_stale = False
|
||||
return
|
||||
|
||||
if embedded_data is not None:
|
||||
self._conn = connector
|
||||
self._path = path
|
||||
self._json = {'Members': embedded_data}
|
||||
self.redfish_version = redfish_version
|
||||
self._registries = registries
|
||||
self._root = root
|
||||
self._is_stale = False
|
||||
return
|
||||
|
||||
super().__init__(connector, path, redfish_version, registries, root)
|
||||
|
||||
@property
|
||||
def members_identities(self):
|
||||
if self._path == "/empty":
|
||||
return []
|
||||
if hasattr(self, '_json') and self._json and 'Members' in self._json:
|
||||
return tuple(m['@odata.id'] for m in self._json['Members']
|
||||
if isinstance(m, dict) and '@odata.id' in m)
|
||||
return super().members_identities
|
||||
|
||||
def get_members(self):
|
||||
if self._path == "/empty":
|
||||
return []
|
||||
|
||||
# Handle embedded PCIeDevices case
|
||||
if hasattr(self, '_json') and self._json and 'Members' in self._json:
|
||||
device_objects = []
|
||||
for member in self._json['Members']:
|
||||
if isinstance(member, dict) and '@odata.id' in member:
|
||||
device_path = member['@odata.id']
|
||||
try:
|
||||
# Fetch device data and create object
|
||||
device_response = self._conn.get(device_path)
|
||||
if device_response:
|
||||
device_obj = PCIeDevice(
|
||||
self._conn, device_path,
|
||||
redfish_version=self.redfish_version,
|
||||
registries=self._registries, root=self._root
|
||||
)
|
||||
device_obj._json = device_response.json()
|
||||
device_objects.append(device_obj)
|
||||
except Exception as e:
|
||||
LOG.warning(
|
||||
'Error fetching PCIe device at path %s: %s',
|
||||
device_path, str(e))
|
||||
continue # Skip failed devices but continue processing
|
||||
return device_objects
|
||||
|
||||
# Standard collection behavior
|
||||
return super().get_members()
|
@@ -32,6 +32,7 @@ from sushy.resources import settings
|
||||
from sushy.resources.system import bios
|
||||
from sushy.resources.system import constants as sys_cons
|
||||
from sushy.resources.system import ethernet_interface
|
||||
from sushy.resources.system import pcie_device
|
||||
from sushy.resources.system import processor
|
||||
from sushy.resources.system import secure_boot
|
||||
from sushy.resources.system import simple_storage as sys_simple_storage
|
||||
@@ -674,6 +675,32 @@ class System(base.ResourceBase):
|
||||
redfish_version=self.redfish_version, registries=self.registries,
|
||||
root=self.root)
|
||||
|
||||
@property
|
||||
@utils.cache_it
|
||||
def pcie_devices(self):
|
||||
"""Property to reference PCIeDeviceCollection instance"""
|
||||
try:
|
||||
pcie_path = utils.get_sub_resource_path_by(self, "PCIeDevices")
|
||||
return pcie_device.PCIeDeviceCollection(
|
||||
self._conn, pcie_path,
|
||||
redfish_version=self.redfish_version,
|
||||
registries=self.registries, root=self.root)
|
||||
except exceptions.MissingAttributeError:
|
||||
# Check if PCIeDevices is embedded in System JSON
|
||||
if (hasattr(self, 'json') and self.json
|
||||
and 'PCIeDevices' in self.json):
|
||||
pcie_devices_data = self.json['PCIeDevices']
|
||||
if isinstance(pcie_devices_data, list) and pcie_devices_data:
|
||||
return pcie_device.PCIeDeviceCollection(
|
||||
self._conn, "/embedded",
|
||||
redfish_version=self.redfish_version,
|
||||
registries=self.registries, root=self.root,
|
||||
embedded_data=pcie_devices_data)
|
||||
return pcie_device.PCIeDeviceCollection(
|
||||
self._conn, "/empty",
|
||||
redfish_version=self.redfish_version,
|
||||
registries=self.registries, root=self.root)
|
||||
|
||||
|
||||
class SystemCollection(base.ResourceCollectionBase):
|
||||
|
||||
|
71
sushy/tests/unit/json_samples/pcie_device.json
Normal file
71
sushy/tests/unit/json_samples/pcie_device.json
Normal file
@@ -0,0 +1,71 @@
|
||||
{
|
||||
"@odata.context": "/redfish/v1/$metadata#PCIeDevice.PCIeDevice",
|
||||
"@odata.etag": "\"1756839817\"",
|
||||
"@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/196-0",
|
||||
"@odata.type": "#PCIeDevice.v1_11_1.PCIeDevice",
|
||||
"AssetTag": null,
|
||||
"Description": "BCM957414A4142CC 10Gb/25Gb Ethernet PCIe",
|
||||
"DeviceType": "MultiFunction",
|
||||
"FirmwareVersion": "224.1.102.0",
|
||||
"Id": "196-0",
|
||||
"Links": {
|
||||
"Chassis": [
|
||||
{
|
||||
"@odata.id": "/redfish/v1/Chassis/System.Embedded.1"
|
||||
}
|
||||
],
|
||||
"Chassis@odata.count": 1,
|
||||
"Oem": {
|
||||
"Dell": {
|
||||
"@odata.type": "#DellOem.v1_3_0.DellOemLinks",
|
||||
"CPUAffinity": [
|
||||
{
|
||||
"@odata.id": "/redfish/v1/Systems/System.Embedded.1/Processors/CPU.Socket.1"
|
||||
}
|
||||
],
|
||||
"CPUAffinity@odata.count": 1
|
||||
}
|
||||
},
|
||||
"PCIeFunctions": [
|
||||
{
|
||||
"@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/196-0/PCIeFunctions/196-0-1"
|
||||
},
|
||||
{
|
||||
"@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/196-0/PCIeFunctions/196-0-0"
|
||||
}
|
||||
],
|
||||
"PCIeFunctions@odata.count": 2,
|
||||
"PCIeFunctions@Redfish.Deprecated": "Please migrate to PCIeFunctions property in the root resource."
|
||||
},
|
||||
"Manufacturer": "Broadcom Inc. and subsidiaries",
|
||||
"Model": null,
|
||||
"Name": "BCM957414A4142CC 10Gb/25Gb Ethernet PCIe",
|
||||
"PartNumber": null,
|
||||
"SKU": null,
|
||||
"SerialNumber": null,
|
||||
"Slot": {
|
||||
"Lanes": 8,
|
||||
"Location": {
|
||||
"PartLocation": {
|
||||
"LocationOrdinalValue": 1,
|
||||
"LocationType": "Slot"
|
||||
}
|
||||
},
|
||||
"PCIeType": "Gen5",
|
||||
"SlotType": "HalfLength"
|
||||
},
|
||||
"PCIeInterface": {
|
||||
"MaxPCIeType": "Gen5",
|
||||
"PCIeType": "Gen5",
|
||||
"MaxLanes": 8,
|
||||
"LanesInUse": 8
|
||||
},
|
||||
"Status": {
|
||||
"State": "Enabled",
|
||||
"Health": "OK",
|
||||
"HealthRollup": "OK"
|
||||
},
|
||||
"PCIeFunctions": {
|
||||
"@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/196-0/PCIeFunctions"
|
||||
}
|
||||
}
|
19
sushy/tests/unit/json_samples/pcie_device_collection.json
Normal file
19
sushy/tests/unit/json_samples/pcie_device_collection.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"@odata.context": "/redfish/v1/$metadata#PCIeDeviceCollection.PCIeDeviceCollection",
|
||||
"@odata.etag": "\"1756839817\"",
|
||||
"@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices",
|
||||
"@odata.type": "#PCIeDeviceCollection.PCIeDeviceCollection",
|
||||
"Description": "Collection of PCIe Devices",
|
||||
"Members": [
|
||||
{
|
||||
"@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/196-0",
|
||||
"Id": "196-0"
|
||||
},
|
||||
{
|
||||
"@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/65-0",
|
||||
"Id": "65-0"
|
||||
}
|
||||
],
|
||||
"Members@odata.count": 2,
|
||||
"Name": "PCIe Device Collection"
|
||||
}
|
48
sushy/tests/unit/json_samples/pcie_device_onboard.json
Normal file
48
sushy/tests/unit/json_samples/pcie_device_onboard.json
Normal file
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"@odata.context": "/redfish/v1/$metadata#PCIeDevice.PCIeDevice",
|
||||
"@odata.etag": "\"1756839815\"",
|
||||
"@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/128-1",
|
||||
"@odata.type": "#PCIeDevice.v1_18_0.PCIeDevice",
|
||||
"AssetTag": null,
|
||||
"Description": "Advanced Micro Devices, Inc. [AMD]",
|
||||
"DeviceType": "MultiFunction",
|
||||
"FirmwareVersion": "",
|
||||
"Id": "128-1",
|
||||
"Links": {
|
||||
"Chassis": [
|
||||
{
|
||||
"@odata.id": "/redfish/v1/Chassis/System.Embedded.1"
|
||||
}
|
||||
],
|
||||
"Chassis@odata.count": 1,
|
||||
"Oem": {
|
||||
"Dell": {
|
||||
"@odata.type": "#DellOem.v1_3_0.DellOemLinks",
|
||||
"CPUAffinity": [],
|
||||
"CPUAffinity@odata.count": 0
|
||||
}
|
||||
},
|
||||
"PCIeFunctions": [
|
||||
{
|
||||
"@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/128-1/PCIeFunctions/128-1-0"
|
||||
}
|
||||
],
|
||||
"PCIeFunctions@odata.count": 1,
|
||||
"PCIeFunctions@Redfish.Deprecated": "Please migrate to PCIeFunctions property in the root resource."
|
||||
},
|
||||
"Manufacturer": "Advanced Micro Devices, Inc. [AMD]",
|
||||
"Model": null,
|
||||
"Name": "Advanced Micro Devices, Inc. [AMD]",
|
||||
"PartNumber": null,
|
||||
"SKU": null,
|
||||
"SerialNumber": null,
|
||||
"Slot": {},
|
||||
"Status": {
|
||||
"State": "Enabled",
|
||||
"Health": "OK",
|
||||
"HealthRollup": "OK"
|
||||
},
|
||||
"PCIeFunctions": {
|
||||
"@odata.id": "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/128-1/PCIeFunctions"
|
||||
}
|
||||
}
|
168
sushy/tests/unit/resources/system/test_pcie_device.py
Normal file
168
sushy/tests/unit/resources/system/test_pcie_device.py
Normal file
@@ -0,0 +1,168 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import json
|
||||
from unittest import mock
|
||||
|
||||
from sushy.resources import constants as res_cons
|
||||
from sushy.resources.system import pcie_device
|
||||
from sushy.tests.unit import base
|
||||
|
||||
|
||||
class PCIeDeviceTestCase(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.conn = mock.Mock()
|
||||
with open('sushy/tests/unit/json_samples/pcie_device.json') as f:
|
||||
self.json_doc = json.load(f)
|
||||
|
||||
self.conn.get.return_value.json.return_value = self.json_doc
|
||||
|
||||
self.pcie_dev = pcie_device.PCIeDevice(
|
||||
self.conn,
|
||||
'/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/196-0',
|
||||
redfish_version='1.0.2')
|
||||
|
||||
def test__parse_attributes(self):
|
||||
self.pcie_dev._parse_attributes(self.json_doc)
|
||||
self.assertEqual('1.0.2', self.pcie_dev.redfish_version)
|
||||
self.assertEqual('196-0', self.pcie_dev.identity)
|
||||
self.assertEqual('BCM957414A4142CC 10Gb/25Gb Ethernet PCIe',
|
||||
self.pcie_dev.name)
|
||||
self.assertEqual('BCM957414A4142CC 10Gb/25Gb Ethernet PCIe',
|
||||
self.pcie_dev.description)
|
||||
self.assertEqual('Broadcom Inc. and subsidiaries',
|
||||
self.pcie_dev.manufacturer)
|
||||
self.assertEqual('MultiFunction', self.pcie_dev.device_type)
|
||||
self.assertEqual('224.1.102.0', self.pcie_dev.firmware_version)
|
||||
self.assertIsNone(self.pcie_dev.asset_tag)
|
||||
self.assertIsNone(self.pcie_dev.serial_number)
|
||||
self.assertIsNone(self.pcie_dev.model)
|
||||
self.assertIsNone(self.pcie_dev.part_number)
|
||||
self.assertIsNone(self.pcie_dev.sku)
|
||||
|
||||
def test_pcie_interface(self):
|
||||
pcie_if = self.pcie_dev.pcie_interface
|
||||
self.assertEqual('Gen5', pcie_if.pcie_type)
|
||||
self.assertEqual('Gen5', pcie_if.max_pcie_type)
|
||||
self.assertEqual(8, pcie_if.lanes_in_use)
|
||||
self.assertEqual(8, pcie_if.max_lanes)
|
||||
|
||||
def test_slot_information(self):
|
||||
slot = self.pcie_dev.slot
|
||||
self.assertEqual('HalfLength', slot.slot_type)
|
||||
self.assertEqual('Gen5', slot.pcie_type)
|
||||
self.assertEqual(8, slot.lanes)
|
||||
self.assertIsNotNone(slot.location)
|
||||
self.assertIsNone(slot.lane_splitting)
|
||||
self.assertIsNone(slot.hot_pluggable)
|
||||
|
||||
def test_status_field(self):
|
||||
status = self.pcie_dev.status
|
||||
self.assertEqual(res_cons.State.ENABLED, status.state)
|
||||
self.assertEqual(res_cons.Health.OK, status.health)
|
||||
self.assertEqual(res_cons.Health.OK, status.health_rollup)
|
||||
|
||||
def test_links_field(self):
|
||||
links = self.pcie_dev.links
|
||||
self.assertIsNotNone(links)
|
||||
|
||||
|
||||
class PCIeDeviceOnboardTestCase(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.conn = mock.Mock()
|
||||
with open('sushy/tests/unit/json_samples/'
|
||||
'pcie_device_onboard.json') as f:
|
||||
self.json_doc = json.load(f)
|
||||
|
||||
self.conn.get.return_value.json.return_value = self.json_doc
|
||||
|
||||
self.onboard_dev = pcie_device.PCIeDevice(
|
||||
self.conn,
|
||||
'/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/128-1',
|
||||
redfish_version='1.0.2')
|
||||
|
||||
def test_onboard_device_attributes(self):
|
||||
self.assertEqual('128-1', self.onboard_dev.identity)
|
||||
self.assertEqual('Advanced Micro Devices, Inc. [AMD]',
|
||||
self.onboard_dev.name)
|
||||
self.assertEqual('Advanced Micro Devices, Inc. [AMD]',
|
||||
self.onboard_dev.manufacturer)
|
||||
self.assertEqual('MultiFunction', self.onboard_dev.device_type)
|
||||
self.assertEqual('', self.onboard_dev.firmware_version)
|
||||
|
||||
def test_onboard_device_empty_slot(self):
|
||||
slot = self.onboard_dev.slot
|
||||
self.assertIsNotNone(slot)
|
||||
# Empty slot object should have None values
|
||||
self.assertIsNone(slot.slot_type)
|
||||
self.assertIsNone(slot.lanes)
|
||||
self.assertIsNone(slot.pcie_type)
|
||||
|
||||
|
||||
class PCIeDeviceCollectionTestCase(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.conn = mock.Mock()
|
||||
with open('sushy/tests/unit/json_samples/'
|
||||
'pcie_device_collection.json') as f:
|
||||
self.json_doc = json.load(f)
|
||||
|
||||
self.conn.get.return_value.json.return_value = self.json_doc
|
||||
|
||||
self.collection = pcie_device.PCIeDeviceCollection(
|
||||
self.conn, '/redfish/v1/Chassis/System.Embedded.1/PCIeDevices',
|
||||
redfish_version='1.0.2')
|
||||
|
||||
def test__parse_attributes(self):
|
||||
self.collection._parse_attributes(self.json_doc)
|
||||
self.assertEqual('1.0.2', self.collection.redfish_version)
|
||||
self.assertEqual('PCIe Device Collection', self.collection.name)
|
||||
self.assertEqual(
|
||||
('/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/196-0',
|
||||
'/redfish/v1/Chassis/System.Embedded.1/PCIeDevices/65-0'),
|
||||
self.collection.members_identities)
|
||||
|
||||
@mock.patch.object(pcie_device, 'PCIeDevice', autospec=True)
|
||||
def test_get_member(self, mock_pcie_device):
|
||||
self.collection.get_member(
|
||||
'/redfish/v1/Chassis/System.Embedded.1/'
|
||||
'PCIeDevices/196-0')
|
||||
mock_pcie_device.assert_called_once_with(
|
||||
self.collection._conn,
|
||||
'/redfish/v1/Chassis/System.Embedded.1/'
|
||||
'PCIeDevices/196-0',
|
||||
redfish_version=self.collection.redfish_version,
|
||||
registries=None, root=self.collection.root)
|
||||
|
||||
@mock.patch.object(pcie_device, 'PCIeDevice', autospec=True)
|
||||
def test_get_members(self, mock_pcie_device):
|
||||
members = self.collection.get_members()
|
||||
calls = [
|
||||
mock.call(self.collection._conn,
|
||||
'/redfish/v1/Chassis/System.Embedded.1/'
|
||||
'PCIeDevices/196-0',
|
||||
redfish_version=self.collection.redfish_version,
|
||||
registries=None, root=self.collection.root),
|
||||
mock.call(self.collection._conn,
|
||||
'/redfish/v1/Chassis/System.Embedded.1/'
|
||||
'PCIeDevices/65-0',
|
||||
redfish_version=self.collection.redfish_version,
|
||||
registries=None, root=self.collection.root)
|
||||
]
|
||||
mock_pcie_device.assert_has_calls(calls)
|
||||
self.assertIsInstance(members, list)
|
||||
self.assertEqual(2, len(members))
|
Reference in New Issue
Block a user