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
|
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',
|
@app.route('/redfish/v1/Systems/<identity>/Actions/ComputerSystem.Reset',
|
||||||
methods=['POST'])
|
methods=['POST'])
|
||||||
@ensure_instance_access
|
@ensure_instance_access
|
||||||
|
@ -439,6 +439,8 @@ class LibvirtDriver(AbstractSystemsDriver):
|
|||||||
def get_boot_mode(self, identity):
|
def get_boot_mode(self, identity):
|
||||||
"""Get computer system boot mode.
|
"""Get computer system boot mode.
|
||||||
|
|
||||||
|
:param identity: libvirt domain name or ID
|
||||||
|
|
||||||
:returns: either *UEFI* or *Legacy* as `str` or `None` if
|
:returns: either *UEFI* or *Legacy* as `str` or `None` if
|
||||||
current boot mode can't be determined
|
current boot mode can't be determined
|
||||||
"""
|
"""
|
||||||
@ -459,6 +461,8 @@ class LibvirtDriver(AbstractSystemsDriver):
|
|||||||
def set_boot_mode(self, identity, boot_mode):
|
def set_boot_mode(self, identity, boot_mode):
|
||||||
"""Set computer system boot mode.
|
"""Set computer system boot mode.
|
||||||
|
|
||||||
|
:param identity: libvirt domain name or ID
|
||||||
|
|
||||||
:param boot_mode: string literal requesting boot mode
|
:param boot_mode: string literal requesting boot mode
|
||||||
change on the system. Valid values are: *UEFI*, *Legacy*.
|
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
|
:returns: available CPU count as `int` or `None` if CPU count
|
||||||
can't be determined
|
can't be determined
|
||||||
"""
|
"""
|
||||||
domain = self._get_domain(identity, readonly=True)
|
|
||||||
|
|
||||||
tree = ET.fromstring(domain.XMLDesc(libvirt.VIR_DOMAIN_XML_INACTIVE))
|
|
||||||
|
|
||||||
total_cpus = 0
|
total_cpus = 0
|
||||||
|
domain = self._get_domain(identity, readonly=True)
|
||||||
|
|
||||||
if domain.isActive():
|
if domain.isActive():
|
||||||
total_cpus = domain.maxVcpus()
|
total_cpus = domain.maxVcpus()
|
||||||
@ -584,7 +585,10 @@ class LibvirtDriver(AbstractSystemsDriver):
|
|||||||
# If we can't get it from maxVcpus() try to find it by
|
# If we can't get it from maxVcpus() try to find it by
|
||||||
# inspecting the domain XML
|
# inspecting the domain XML
|
||||||
if total_cpus <= 0:
|
if total_cpus <= 0:
|
||||||
|
tree = ET.fromstring(
|
||||||
|
domain.XMLDesc(libvirt.VIR_DOMAIN_XML_INACTIVE))
|
||||||
vcpu_element = tree.find('.//vcpu')
|
vcpu_element = tree.find('.//vcpu')
|
||||||
|
|
||||||
if vcpu_element is not None:
|
if vcpu_element is not None:
|
||||||
total_cpus = int(vcpu_element.text)
|
total_cpus = int(vcpu_element.text)
|
||||||
|
|
||||||
@ -747,10 +751,45 @@ class LibvirtDriver(AbstractSystemsDriver):
|
|||||||
for iface in tree.findall(
|
for iface in tree.findall(
|
||||||
".//devices/interface[@type='network']/mac")]
|
".//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):
|
def get_boot_image(self, identity, device):
|
||||||
"""Get backend VM boot image info
|
"""Get backend VM boot image info
|
||||||
|
|
||||||
:param identity: node name or ID
|
:param identity: libvirt domain name or ID
|
||||||
:param device: device type (from
|
:param device: device type (from
|
||||||
`sushy_tools.emulator.constants`)
|
`sushy_tools.emulator.constants`)
|
||||||
:returns: a `tuple` of (boot_image, write_protected, inserted)
|
:returns: a `tuple` of (boot_image, write_protected, inserted)
|
||||||
@ -981,7 +1020,7 @@ class LibvirtDriver(AbstractSystemsDriver):
|
|||||||
write_protected=True):
|
write_protected=True):
|
||||||
"""Set backend VM boot image
|
"""Set backend VM boot image
|
||||||
|
|
||||||
:param identity: node name or ID
|
:param identity: libvirt domain name or ID
|
||||||
:param device: device type (from
|
:param device: device type (from
|
||||||
`sushy_tools.emulator.constants`)
|
`sushy_tools.emulator.constants`)
|
||||||
:param boot_image: path to the image file or `None` to remove
|
: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)
|
nics = self.test_driver.get_nics(self.uuid)
|
||||||
self.assertEqual([], nics)
|
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)
|
@mock.patch('libvirt.openReadOnly', autospec=True)
|
||||||
def test_get_simple_storage_collection(self, libvirt_mock):
|
def test_get_simple_storage_collection(self, libvirt_mock):
|
||||||
with open('sushy_tools/tests/unit/emulator/'
|
with open('sushy_tools/tests/unit/emulator/'
|
||||||
|
Loading…
x
Reference in New Issue
Block a user