Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
83 changes: 44 additions & 39 deletions checkbox-ng/checkbox_ng/support/lib/dmi.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,47 +19,50 @@
from checkbox_ng.support.lib.conversion import string_to_type


# See also 3.3.4.1 of the "System Management BIOS Reference Specification,
# Version 2.6.1" (Preliminary Standard) document, available from
# http://www.dmtf.org/standards/smbios.
# See also 7.4.1 "System Enclosure or Chassis Types" of the "System Management
# BIOS Specification, Version 3.9.0" (DSP0134), available
# from https://www.dmtf.org/standards/smbios.
class Dmi:
chassis = (
("Undefined", "unknown"), # 0x00
("Other", "unknown"),
("Unknown", "unknown"),
("Desktop", "desktop"),
("Low Profile Desktop", "desktop"),
("Pizza Box", "server"),
("Mini Tower", "desktop"),
("Tower", "desktop"),
("Portable", "laptop"),
("Laptop", "laptop"),
("Notebook", "laptop"),
("Hand Held", "handheld"),
("Docking Station", "laptop"),
("All In One", "unknown"),
("Sub Notebook", "laptop"),
("Space-saving", "desktop"),
("Lunch Box", "unknown"),
("Main Server Chassis", "server"),
("Expansion Chassis", "unknown"),
("Sub Chassis", "unknown"),
("Bus Expansion Chassis", "unknown"),
("Peripheral Chassis", "unknown"),
("RAID Chassis", "unknown"),
("Rack Mount Chassis", "unknown"),
("Sealed-case PC", "unknown"),
("Multi-system", "unknown"),
("CompactPCI", "unknonw"),
("AdvancedTCA", "unknown"),
("Blade", "server"),
("Blade Enclosure", "unknown"),
chassis_types = (
"Undefined", # 0x00 placeholder for SMBIOS alignment
"Other",
"Unknown",
"Desktop",
"Low Profile Desktop",
"Pizza Box",
"Mini Tower",
"Tower",
"Portable",
"Laptop",
"Notebook",
"Hand Held",
"Docking Station",
"All In One",
"Sub Notebook",
"Space-saving",
"Lunch Box",
"Main Server Chassis",
"Expansion Chassis",
"Sub Chassis",
"Bus Expansion Chassis",
"Peripheral Chassis",
"RAID Chassis",
"Rack Mount Chassis",
"Sealed-case PC",
"Multi-system",
"Compact PCI",
"Advanced TCA",
"Blade",
"Blade Enclosure",
"Tablet",
"Convertible",
"Detachable",
"IoT Gateway",
"Embedded PC",
"Mini PC",
"Stick PC",
)

chassis_names = tuple(c[0] for c in chassis)
chassis_types = tuple(c[1] for c in chassis)
chassis_name_to_type = dict(chassis)

type_names = (
"BIOS", # 0x00
"System",
Expand Down Expand Up @@ -185,9 +188,11 @@ def product(self):
type_string = self._attributes.get("chassis_type", "0")
try:
type_index = int(type_string)
return Dmi.chassis_names[type_index]
except ValueError:
return type_string
if 0 <= type_index < len(Dmi.chassis_types):
return Dmi.chassis_types[type_index]
return "Unknown"

for name in "name", "version":
attribute = "%s_%s" % (self.category.lower(), name)
Expand Down
15 changes: 15 additions & 0 deletions checkbox-ng/checkbox_ng/support/parsers/tests/test_dmidecode.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ def resource_filename(name, path):
except ImportError:
from pkg_resources import resource_filename

from checkbox_ng.support.lib.dmi import Dmi, DmiDevice
from checkbox_ng.support.parsers.dmidecode import DmidecodeParser
from checkbox_ng.support.parsers.tests.test_dmi import TestDmiMixin, DmiResult

Expand Down Expand Up @@ -206,3 +207,17 @@ def test_system_product_name(self):
"family": "System X",
}
self.assertDictEqual(dmi_device.raw_attributes, correct_values)


class TestChassisProduct(TestCase):
def make_chassis(self, chassis_type):
return DmiDevice({"chassis_type": chassis_type}, "CHASSIS")

def test_out_of_range_index(self):
"""Test that an index beyond the known list returns unknown."""
index = str(len(Dmi.chassis_types))
self.assertEqual(self.make_chassis(index).product, "Unknown")

def test_non_numeric_type(self):
"""Test that a non-numeric type returns the type string."""
self.assertEqual(self.make_chassis("Notebook").product, "Notebook")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, we are getting away from that, call the script from a collector, that will add the information as a system_information

Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@
"{{ key }}": "{{ lsb_resource[key] }}"{%- if not loop.last -%},{%- endif %}
{%- endfor %}
},
{%- endif %}
{%- if ns ~ 'dmi' in state.resource_map %}
{%- for dmi_resource in state.resource_map[ns ~ 'dmi'] if dmi_resource.chassis %}
"chassis": "{{ dmi_resource.chassis }}",
{%- endfor %}
{%- endif %}
Comment thread
diohe0311 marked this conversation as resolved.
"results": [
{%- for job_id, job_state in job_state_map|dictsort if job_state.result.outcome != None and job_state.job.plugin != "attachment" %}
Expand Down
2 changes: 2 additions & 0 deletions providers/resource/bin/dmi_resource.py

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why?

Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ def addDmiDevice(self, device):
if attribute == "product" and value:
print("{}: {}".format("sane_product", sane_product(value)))
print("{}: {}".format("display_type", display_type(value)))
if device.category == "CHASSIS":
print("{}: {}".format("chassis", value))

print()

Expand Down
25 changes: 23 additions & 2 deletions providers/resource/tests/test_dmi_resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@
# You should have received a copy of the GNU General Public License
# along with Checkbox. If not, see <http://www.gnu.org/licenses/>.

import unittest
from unittest import TestCase
from unittest.mock import MagicMock

import contextlib
import io

from checkbox_ng.support.lib.dmi import DmiDevice

import dmi_resource

Expand Down Expand Up @@ -86,3 +89,21 @@ def test_display_type_unknown(self):
products = ["strange-iot-product"]
category = set(map(dmi_resource.display_type, products))
self.assertEqual(category, {"external"})


class TestDmiResultChassis(TestCase):
def output_for(self, device):
stream = io.StringIO()
with contextlib.redirect_stdout(stream):
dmi_resource.DmiResult().addDmiDevice(device)
return stream.getvalue()

def test_chassis_device_outputs_mapped_chassis_type(self):
"""Test that a CHASSIS device outputs its mapped chassis type."""
device = DmiDevice({"chassis_type": "10"}, "CHASSIS")
self.assertIn("chassis: Notebook", self.output_for(device))

def test_chassis_field_only_outputs_for_chassis_devices(self):
"""Test that the chassis field is only included for CHASSIS devices."""
device = DmiDevice({"system_name": "20AMOS3"}, "SYSTEM")
self.assertNotIn("chassis:", self.output_for(device))
3 changes: 3 additions & 0 deletions submission-schema/schema.json

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above, use the system information and update it!

Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,9 @@
},
"buildstamp": {
"type": "string"
},
"chassis": {
"type": "string"
}
},
"required": [
Expand Down
Loading