~kissiel/checkbox/fix-1420352

« back to all changes in this revision

Viewing changes to checkbox-support/checkbox_support/parsers/dmidecode.py

  • Committer: Sylvain Pineau
  • Date: 2014-01-07 13:39:38 UTC
  • mto: This revision was merged to the branch mainline in revision 2588.
  • Revision ID: sylvain.pineau@canonical.com-20140107133938-46v5ehofwa9whl1e
checkbox-support: Copy required modules from checkbox-old/checkbox

and their corresponding tests

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#
 
2
# This file is part of Checkbox.
 
3
#
 
4
# Copyright 2011 Canonical Ltd.
 
5
#
 
6
# Checkbox is free software: you can redistribute it and/or modify
 
7
# it under the terms of the GNU General Public License version 3,
 
8
# as published by the Free Software Foundation.
 
9
 
 
10
#
 
11
# Checkbox is distributed in the hope that it will be useful,
 
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
# GNU General Public License for more details.
 
15
#
 
16
# You should have received a copy of the GNU General Public License
 
17
# along with Checkbox.  If not, see <http://www.gnu.org/licenses/>.
 
18
#
 
19
import re
 
20
 
 
21
from string import (
 
22
    hexdigits,
 
23
    ascii_uppercase,
 
24
    )
 
25
 
 
26
from checkbox.lib.dmi import (
 
27
    Dmi,
 
28
    DmiDevice,
 
29
    )
 
30
 
 
31
 
 
32
HANDLE_RE = re.compile(
 
33
    r"^Handle (?P<handle>0x[%s]{4}), "
 
34
    r"DMI type (?P<type>\d+), "
 
35
    r"(?P<size>\d+) bytes$"
 
36
    % hexdigits)
 
37
KEY_VALUE_RE = re.compile(
 
38
    r"^\t(?P<key>[%s].+):( (?P<value>.+))?$"
 
39
    % ascii_uppercase)
 
40
 
 
41
 
 
42
class DmidecodeParser:
 
43
    """Parser for the dmidecode command."""
 
44
 
 
45
    _key_map = {
 
46
        "ID": "serial",
 
47
        "Manufacturer": "vendor",
 
48
        "Product Name": "name",
 
49
        "Serial Number": "serial",
 
50
        "Type": "type",
 
51
        "Vendor": "vendor",
 
52
        "Version": "version",
 
53
        "Size": "size",
 
54
        "Form Factor": "form",
 
55
        }
 
56
 
 
57
    def __init__(self, stream):
 
58
        self.stream = stream
 
59
 
 
60
    def _parseKey(self, key):
 
61
        return self._key_map.get(key)
 
62
 
 
63
    def _parseValue(self, value):
 
64
        if value is not None:
 
65
            value = value.strip()
 
66
            if not value:
 
67
                value = None
 
68
 
 
69
        return value
 
70
 
 
71
    def run(self, result):
 
72
        output = self.stream.read()
 
73
        for record in re.split(r"\n{2,}", output):
 
74
            record = record.strip()
 
75
            # Skip empty records
 
76
            if not record:
 
77
                continue
 
78
 
 
79
            # Skip header record
 
80
            lines = record.split("\n")
 
81
            line = lines.pop(0)
 
82
            if line.startswith("#"):
 
83
                continue
 
84
 
 
85
            # Skip records with an unsupported handle
 
86
            match = HANDLE_RE.match(line)
 
87
            if not match:
 
88
                continue
 
89
 
 
90
            # Skip records that are empty or inactive
 
91
            if not lines or lines.pop(0) == "Inactive":
 
92
                continue
 
93
 
 
94
            # Skip disabled entries and end-of-table marker
 
95
            type_index = int(match.group("type"))
 
96
            if type_index >= len(Dmi.type_names):
 
97
                continue
 
98
 
 
99
            category = Dmi.type_names[type_index]
 
100
            category = category.upper().split(" ")[-1]
 
101
            if category not in (
 
102
                "BOARD", "BIOS", "CHASSIS", "DEVICE", "PROCESSOR", "SYSTEM"):
 
103
                continue
 
104
 
 
105
            # Parse attributes
 
106
            attributes = {}
 
107
 
 
108
            for line in lines:
 
109
                # Skip lines with an unsupported key/value pair
 
110
                match = KEY_VALUE_RE.match(line)
 
111
                if not match:
 
112
                    continue
 
113
 
 
114
                # Skip lines with an unsupported key
 
115
                key = self._parseKey(match.group("key"))
 
116
                if not key:
 
117
                    continue
 
118
 
 
119
                key = "%s_%s" % (category.lower(), key)
 
120
                value = self._parseValue(match.group("value"))
 
121
                attributes[key] = value
 
122
 
 
123
            device = DmiDevice(attributes, category)
 
124
            result.addDmiDevice(device)
 
125
 
 
126
        return result