Adding basic support for processors schema
Adds logic to provide basic support for Redfish Processor schema [1] [1] https://redfish.dmtf.org/schemas/v1/Processor.v1_10_0.json Story: 2007454 Task: 39128 Change-Id: I0eee22a18dde54e887e2a5d3ed1db141fec163f7
This commit is contained in:
parent
3a05eed4d2
commit
ef0baa7215
@ -155,3 +155,4 @@ SUSHY_EMULATOR_VOLUMES = {
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,4 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Adds basic support for Redfish Processor schema.
|
@ -568,6 +568,33 @@ def ethernet_interface(identity, nic_id):
|
||||
return 'Not found', 404
|
||||
|
||||
|
||||
@app.route('/redfish/v1/Systems/<identity>/Processors',
|
||||
methods=['GET'])
|
||||
@ensure_instance_access
|
||||
@returns_json
|
||||
def processors_collection(identity):
|
||||
processors = app.systems.get_processors(identity)
|
||||
|
||||
return flask.render_template(
|
||||
'processors_collection.json', identity=identity,
|
||||
processors=processors)
|
||||
|
||||
|
||||
@app.route('/redfish/v1/Systems/<identity>/Processors/<processor_id>',
|
||||
methods=['GET'])
|
||||
@ensure_instance_access
|
||||
@returns_json
|
||||
def processor(identity, processor_id):
|
||||
processors = app.systems.get_processors(identity)
|
||||
|
||||
for proc in processors:
|
||||
if proc['id'] == processor_id:
|
||||
return flask.render_template(
|
||||
'processor.json', identity=identity, processor=proc)
|
||||
|
||||
return 'Not found', 404
|
||||
|
||||
|
||||
@app.route('/redfish/v1/Systems/<identity>/Actions/ComputerSystem.Reset',
|
||||
methods=['POST'])
|
||||
@ensure_instance_access
|
||||
|
@ -439,6 +439,8 @@ class LibvirtDriver(AbstractSystemsDriver):
|
||||
def get_boot_mode(self, identity):
|
||||
"""Get computer system boot mode.
|
||||
|
||||
:param identity: libvirt domain name or ID
|
||||
|
||||
:returns: either *UEFI* or *Legacy* as `str` or `None` if
|
||||
current boot mode can't be determined
|
||||
"""
|
||||
@ -459,6 +461,8 @@ class LibvirtDriver(AbstractSystemsDriver):
|
||||
def set_boot_mode(self, identity, boot_mode):
|
||||
"""Set computer system boot mode.
|
||||
|
||||
:param identity: libvirt domain name or ID
|
||||
|
||||
:param boot_mode: string literal requesting boot mode
|
||||
change on the system. Valid values are: *UEFI*, *Legacy*.
|
||||
|
||||
@ -572,11 +576,8 @@ class LibvirtDriver(AbstractSystemsDriver):
|
||||
:returns: available CPU count as `int` or `None` if CPU count
|
||||
can't be determined
|
||||
"""
|
||||
domain = self._get_domain(identity, readonly=True)
|
||||
|
||||
tree = ET.fromstring(domain.XMLDesc(libvirt.VIR_DOMAIN_XML_INACTIVE))
|
||||
|
||||
total_cpus = 0
|
||||
domain = self._get_domain(identity, readonly=True)
|
||||
|
||||
if domain.isActive():
|
||||
total_cpus = domain.maxVcpus()
|
||||
@ -584,7 +585,10 @@ class LibvirtDriver(AbstractSystemsDriver):
|
||||
# If we can't get it from maxVcpus() try to find it by
|
||||
# inspecting the domain XML
|
||||
if total_cpus <= 0:
|
||||
tree = ET.fromstring(
|
||||
domain.XMLDesc(libvirt.VIR_DOMAIN_XML_INACTIVE))
|
||||
vcpu_element = tree.find('.//vcpu')
|
||||
|
||||
if vcpu_element is not None:
|
||||
total_cpus = int(vcpu_element.text)
|
||||
|
||||
@ -747,10 +751,45 @@ class LibvirtDriver(AbstractSystemsDriver):
|
||||
for iface in tree.findall(
|
||||
".//devices/interface[@type='network']/mac")]
|
||||
|
||||
def get_processors(self, identity):
|
||||
"""Get list of processors
|
||||
|
||||
:param identity: libvirt domain name or ID
|
||||
|
||||
:returns: list of processors dict with their attributes
|
||||
"""
|
||||
domain = self._get_domain(identity, readonly=True)
|
||||
processors_count = self.get_total_cpus(identity)
|
||||
|
||||
# NOTE(rpittau) not a lot we can provide if the domain is not active
|
||||
processors = [{'id': 'CPU{0}'.format(x),
|
||||
'socket': 'CPU {0}'.format(x)}
|
||||
for x in range(processors_count)]
|
||||
|
||||
if domain.isActive():
|
||||
tree = ET.fromstring(domain.XMLDesc())
|
||||
|
||||
model = tree.find('.//cpu/model').text
|
||||
vendor = tree.find('.//cpu/vendor').text
|
||||
try:
|
||||
cores = tree.find('.//cpu/topology').get('cores')
|
||||
threads = tree.find('.//cpu/topology').get('threads')
|
||||
except AttributeError:
|
||||
cores = 'N/A'
|
||||
threads = 'N/A'
|
||||
|
||||
for processor in processors:
|
||||
processor['model'] = model
|
||||
processor['vendor'] = vendor
|
||||
processor['cores'] = cores
|
||||
processor['threads'] = threads
|
||||
|
||||
return processors
|
||||
|
||||
def get_boot_image(self, identity, device):
|
||||
"""Get backend VM boot image info
|
||||
|
||||
:param identity: node name or ID
|
||||
:param identity: libvirt domain name or ID
|
||||
:param device: device type (from
|
||||
`sushy_tools.emulator.constants`)
|
||||
:returns: a `tuple` of (boot_image, write_protected, inserted)
|
||||
@ -981,7 +1020,7 @@ class LibvirtDriver(AbstractSystemsDriver):
|
||||
write_protected=True):
|
||||
"""Set backend VM boot image
|
||||
|
||||
:param identity: node name or ID
|
||||
:param identity: libvirt domain name or ID
|
||||
:param device: device type (from
|
||||
`sushy_tools.emulator.constants`)
|
||||
:param boot_image: path to the image file or `None` to remove
|
||||
|
21
sushy_tools/emulator/templates/processor.json
Normal file
21
sushy_tools/emulator/templates/processor.json
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"@odata.type": "#Processor.v1_0_7.Processor",
|
||||
"Id": {{ processor['id']|string|tojson }},
|
||||
"Name": "Processor",
|
||||
"Socket": {{ processor['socket']|string|tojson }},
|
||||
"ProcessorType": "CPU",
|
||||
"ProcessorArchitecture": "x86",
|
||||
"InstructionSet": "x86-64",
|
||||
"Manufacturer": {{ processor['vendor']|string|tojson }},
|
||||
"Model": {{ processor['model']|string|tojson }},
|
||||
"TotalCores": {{ processor['cores']|string|tojson }},
|
||||
"TotalThreads": {{ processor['threads']|string|tojson }},
|
||||
"Status": {
|
||||
"@odata.type": "#Resource.Status",
|
||||
"State": "Enabled",
|
||||
"Health": "OK"
|
||||
},
|
||||
"@odata.context": "/redfish/v1/$metadata#Processor.Processor",
|
||||
"@odata.id": {{ "/redfish/v1/Systems/%s/Processors/%s"|format(identity, processor['Id'])|tojson }},
|
||||
"@Redfish.Copyright": "Copyright 2014-2019 DMTF. For the full DMTF copyright policy, see http://www.dmtf.org/about/policies/copyright"
|
||||
}
|
15
sushy_tools/emulator/templates/processors_collection.json
Normal file
15
sushy_tools/emulator/templates/processors_collection.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"@odata.type": "#ProcessorCollection.ProcessorCollection",
|
||||
"Name": "Processors Collection",
|
||||
"Members@odata.count": {{ processors|length}},
|
||||
"Members": [
|
||||
{% for processor in processors %}
|
||||
{
|
||||
"@odata.id": {{ "/redfish/v1/Systems/%s/Processors/%s"|format(identity, processor.id)|tojson }}
|
||||
}{% if not loop.last %},{% endif %}
|
||||
{% endfor %}
|
||||
],
|
||||
"@odata.context": "/redfish/v1/$metadata#ProcessorCollection.ProcessorCollection",
|
||||
"@odata.id": {{ "/redfish/v1/Systems/%s/Processors/%s"|format(identity, processor)|tojson }},
|
||||
"@Redfish.Copyright": "Copyright 2014-2020 DMTF. For the full DMTF copyright policy, see http://www.dmtf.org/about/policies/copyright"
|
||||
}
|
32
sushy_tools/tests/unit/emulator/domain_processors.xml
Normal file
32
sushy_tools/tests/unit/emulator/domain_processors.xml
Normal file
@ -0,0 +1,32 @@
|
||||
<domain type='kvm' id='1'>
|
||||
<name>test-node</name>
|
||||
<uuid>da64d3a4-0b06-428b-9afb-73b4a4101bb3</uuid>
|
||||
<memory unit='KiB'>1048576</memory>
|
||||
<currentMemory unit='KiB'>1048576</currentMemory>
|
||||
<vcpu placement='static'>2</vcpu>
|
||||
<resource>
|
||||
<partition>/machine</partition>
|
||||
</resource>
|
||||
<os>
|
||||
<type arch='x86_64' machine='pc-q35-5.1'>hvm</type>
|
||||
<boot dev='hd'/>
|
||||
</os>
|
||||
<features>
|
||||
<acpi/>
|
||||
<apic/>
|
||||
</features>
|
||||
<cpu match='exact'>
|
||||
<model fallback='allow'>core2duo</model>
|
||||
<vendor>Intel</vendor>
|
||||
<topology sockets='1' cores='2' threads='1'/>
|
||||
<feature policy='disable' name='lahf_lm'/>
|
||||
</cpu>
|
||||
<clock offset='utc'>
|
||||
<timer name='rtc' tickpolicy='catchup'/>
|
||||
<timer name='pit' tickpolicy='delay'/>
|
||||
<timer name='hpet' present='no'/>
|
||||
</clock>
|
||||
<on_poweroff>destroy</on_poweroff>
|
||||
<on_reboot>restart</on_reboot>
|
||||
<on_crash>destroy</on_crash>
|
||||
</domain>
|
@ -917,6 +917,32 @@ class LibvirtDriverTestCase(base.BaseTestCase):
|
||||
nics = self.test_driver.get_nics(self.uuid)
|
||||
self.assertEqual([], nics)
|
||||
|
||||
@mock.patch('libvirt.openReadOnly', autospec=True)
|
||||
def test_get_processors(self, libvirt_mock):
|
||||
with open(
|
||||
'sushy_tools/tests/unit/emulator/domain_processors.xml') as f:
|
||||
domain_xml = f.read()
|
||||
|
||||
conn_mock = libvirt_mock.return_value
|
||||
domain_mock = conn_mock.lookupByUUID.return_value
|
||||
domain_mock.XMLDesc.return_value = domain_xml
|
||||
domain_mock.maxVcpus.return_value = 2
|
||||
|
||||
processors = self.test_driver.get_processors(self.uuid)
|
||||
self.assertEqual([{'cores': '2',
|
||||
'id': 'CPU0',
|
||||
'model': 'core2duo',
|
||||
'socket': 'CPU 0',
|
||||
'threads': '1',
|
||||
'vendor': 'Intel'},
|
||||
{'cores': '2',
|
||||
'id': 'CPU1',
|
||||
'model': 'core2duo',
|
||||
'socket': 'CPU 1',
|
||||
'threads': '1',
|
||||
'vendor': 'Intel'}],
|
||||
sorted(processors, key=lambda k: k['id']))
|
||||
|
||||
@mock.patch('libvirt.openReadOnly', autospec=True)
|
||||
def test_get_simple_storage_collection(self, libvirt_mock):
|
||||
with open('sushy_tools/tests/unit/emulator/'
|
||||
|
Loading…
Reference in New Issue
Block a user