~launchpad-results/launchpad-results/trunk

« back to all changes in this revision

Viewing changes to lib/lpresults/xunit/parsers/udevadm.py

  • Committer: Marc Tardif
  • Date: 2011-09-19 21:09:02 UTC
  • Revision ID: marc.tardif@canonical.com-20110919210902-32f23dwivc6tua56
Changed results to only return the last state which fixes bug #852007.

Show diffs side-by-side

added added

removed removed

Lines of Context:
8
8
    ]
9
9
 
10
10
import re
 
11
import string
11
12
 
12
13
from lpresults.xunit.parsers.bit import (
13
14
    get_bitmask,
18
19
from lpresults.xunit.parsers.usb import Usb
19
20
 
20
21
 
 
22
PCI_PATTERN = r"^pci:" \
 
23
    "v(?P<vendor_id>[%(hex)s]{8})" \
 
24
    "d(?P<product_id>[%(hex)s]{8})" \
 
25
    "sv(?P<subvendor_id>[%(hex)s]{8})" \
 
26
    "sd(?P<subproduct_id>[%(hex)s]{8})" \
 
27
    "bc(?P<class>[%(hex)s]{2})" \
 
28
    "sc(?P<subclass>[%(hex)s]{2})" \
 
29
    "i(?P<interface>[%(hex)s]{2})" \
 
30
    % {"hex": string.hexdigits}
 
31
PCI_RE = re.compile(PCI_PATTERN)
 
32
 
 
33
PNP_PATTERN = r"^acpi:" \
 
34
    "(?P<vendor_name>[%(upper)s]{3})" \
 
35
    "(?P<product_id>[%(hex)s]{4}):" \
 
36
    % {"upper": string.uppercase, "hex": string.hexdigits}
 
37
PNP_RE = re.compile(PNP_PATTERN)
 
38
 
 
39
USB_PATTERN = r"^usb:" \
 
40
    "v(?P<vendor_id>[%(hex)s]{4})" \
 
41
    "p(?P<product_id>[%(hex)s]{4})" \
 
42
    "d(?P<revision>[%(hex)s]{4})" \
 
43
    "dc(?P<class>[%(hex)s]{2})" \
 
44
    "dsc(?P<subclass>[%(hex)s]{2})" \
 
45
    "dp(?P<protocol>[%(hex)s]{2})" \
 
46
    "ic(?P<interface_class>[%(hex)s]{2})" \
 
47
    "isc(?P<interface_subclass>[%(hex)s]{2})" \
 
48
    "ip(?P<interface_protocol>[%(hex)s]{2})" \
 
49
    % {"hex": string.hexdigits}
 
50
USB_RE = re.compile(USB_PATTERN)
 
51
 
 
52
SCSI_PATTERN = r"^scsi:" \
 
53
    "t-0x(?P<type>[%(hex)s]{2})" \
 
54
    % {"hex": string.hexdigits}
 
55
SCSI_RE = re.compile(SCSI_PATTERN)
 
56
 
 
57
 
21
58
class UdevadmDevice:
22
 
    __slots__ = ("_environment",)
 
59
    __slots__ = ("_environment", "_stack",)
23
60
 
24
 
    def __init__(self, environment):
 
61
    def __init__(self, environment, stack=[]):
25
62
        super(UdevadmDevice, self).__init__()
26
63
        self._environment = environment
 
64
        self._stack = stack
27
65
 
28
66
    @property
29
67
    def bus(self):
 
68
        # Change the bus from 'acpi' to 'pnp' for some devices
 
69
        if PNP_RE.match(self._environment.get("MODALIAS", "")) \
 
70
           and self.path.endswith(":00"):
 
71
            return "pnp"
 
72
 
 
73
        # Change the bus from 'block' to parent
 
74
        if self._environment.get("DEVTYPE") == "disk" and self._stack:
 
75
            return self._stack[-1]._environment.get("SUBSYSTEM")
 
76
 
30
77
        return self._environment.get("SUBSYSTEM")
31
78
 
32
79
    @property
159
206
                if "ID_DRIVE_FLOPPY" in self._environment:
160
207
                    return "FLOPPY"
161
208
 
 
209
            if devtype == "scsi_device":
 
210
                match = SCSI_RE.match(self._environment.get("MODALIAS", ""))
 
211
                type = int(match.group("type"), 16) if match else -1
 
212
 
 
213
                # Check FLASH drives, see /lib/udev/rules.d/80-udisks.rules
 
214
                if type in (0, 7, 14) \
 
215
                   and not any(d.driver == "rts_pstor" for d in self._stack):
 
216
                    return "DISK"
 
217
 
 
218
                if type == 1:
 
219
                    return "TAPE"
 
220
 
 
221
                if type == 2:
 
222
                    return "PRINTER"
 
223
 
 
224
                if type in (4, 5):
 
225
                    return "CDROM"
 
226
 
 
227
                if type == 6:
 
228
                    return "SCANNER"
 
229
 
 
230
                if type == 12:
 
231
                    return "RAID"
 
232
 
162
233
        if "DRIVER" in self._environment:
163
234
            if self._environment["DRIVER"] == "floppy":
164
235
                return "FLOPPY"
173
244
        if "DRIVER" in self._environment:
174
245
            return self._environment["DRIVER"]
175
246
 
176
 
        if "ID_USB_DRIVER" in self._environment:
177
 
            return self._environment["ID_USB_DRIVER"]
 
247
        # Check parent device for driver
 
248
        if self._stack:
 
249
            parent = self._stack[-1]
 
250
            if "DRIVER" in parent._environment:
 
251
                return parent._environment["DRIVER"]
178
252
 
179
253
        return None
180
254
 
185
259
    @property
186
260
    def product_id(self):
187
261
        # pci
188
 
        if "PCI_ID" in self._environment:
189
 
            vendor_id, product_id = self._environment["PCI_ID"].split(":")
190
 
            return int(product_id, 16)
191
 
 
192
 
        # usb interface
193
 
        if "PRODUCT" in self._environment \
194
 
           and self._environment.get("DEVTYPE") == "usb_interface":
195
 
            product_id = self._environment["PRODUCT"].split("/")[1]
196
 
            return int(product_id, 16)
197
 
 
198
 
        # usb device
199
 
        if "ID_MODEL_ID" in self._environment:
200
 
            return int(self._environment["ID_MODEL_ID"], 16)
 
262
        match = PCI_RE.match(self._environment.get("MODALIAS", ""))
 
263
        if match:
 
264
            return int(match.group("product_id"), 16)
 
265
 
 
266
        # usb
 
267
        match = USB_RE.match(self._environment.get("MODALIAS", ""))
 
268
        if match:
 
269
            return int(match.group("product_id"), 16)
 
270
 
 
271
        # pnp
 
272
        match = PNP_RE.match(self._environment.get("MODALIAS", ""))
 
273
        if match:
 
274
            product_id = int(match.group("product_id"), 16)
 
275
            # Ignore interrupt controllers
 
276
            if product_id > 0x0100:
 
277
                return product_id
201
278
 
202
279
        return None
203
280
 
204
281
    @property
205
282
    def vendor_id(self):
206
283
        # pci
207
 
        if "PCI_ID" in self._environment:
208
 
            vendor_id, product_id = self._environment["PCI_ID"].split(":")
209
 
            return int(vendor_id, 16)
210
 
 
211
 
        # usb interface
212
 
        if "PRODUCT" in self._environment \
213
 
           and self._environment.get("DEVTYPE") == "usb_interface":
214
 
            vendor_id, product_id, revision \
215
 
                = self._environment["PRODUCT"].split("/")
216
 
            return int(vendor_id, 16)
217
 
 
218
 
        # usb device
219
 
        if "ID_VENDOR_ID" in self._environment:
220
 
            return int(self._environment["ID_VENDOR_ID"], 16)
 
284
        match = PCI_RE.match(self._environment.get("MODALIAS", ""))
 
285
        if match:
 
286
            return int(match.group("vendor_id"), 16)
 
287
 
 
288
        # usb
 
289
        match = USB_RE.match(self._environment.get("MODALIAS", ""))
 
290
        if match:
 
291
            return int(match.group("vendor_id"), 16)
221
292
 
222
293
        return None
223
294
 
247
318
            if element in self._environment:
248
319
                return self._environment[element].strip('"')
249
320
 
 
321
        # disk
 
322
        if self._environment.get("DEVTYPE") == "scsi_device":
 
323
            for device in reversed(self._stack):
 
324
                if device._environment.get("ID_BUS") == "usb":
 
325
                    model = device._environment["ID_MODEL_ENC"]
 
326
                    return model.decode("string-escape").strip()
 
327
 
 
328
        if self._environment.get("DEVTYPE") == "disk" \
 
329
           and self._environment.get("ID_BUS") == "ata":
 
330
            model = self._environment["ID_MODEL_ENC"]
 
331
            return model.decode("string-escape").strip()
 
332
 
250
333
        # floppy
251
334
        if self.driver == "floppy":
252
 
            return "Platform Device"
 
335
            return u"Platform Device"
253
336
 
254
337
        return None
255
338
 
261
344
        if "POWER_SUPPLY_MANUFACTURER" in self._environment:
262
345
            return self._environment["POWER_SUPPLY_MANUFACTURER"]
263
346
 
 
347
        # pnp
 
348
        match = PNP_RE.match(self._environment.get("MODALIAS", ""))
 
349
        if match:
 
350
            return match.group("vendor_name")
 
351
 
 
352
        # disk
 
353
        if self._environment.get("DEVTYPE") == "scsi_device":
 
354
            for device in reversed(self._stack):
 
355
                if device._environment.get("ID_BUS") == "usb":
 
356
                    vendor = device._environment["ID_VENDOR_ENC"]
 
357
                    return vendor.decode("string-escape").strip()
 
358
 
264
359
        return None
265
360
 
266
361
 
288
383
             and device.subvendor_id is None)):
289
384
            return True
290
385
 
291
 
        # Ignore virtual devices except for dmi information
292
 
        if device.bus != "dmi" \
293
 
           and "virtual" in device.path.split("/"):
 
386
        # Ignore ACPI devices
 
387
        if device.bus == "acpi":
294
388
            return True
295
389
 
296
390
        return False
304
398
        line_pattern = re.compile(r"(?P<key>[A-Z]):\s*(?P<value>.*)")
305
399
        multi_pattern = re.compile(r"(?P<key>[^=]+)=(?P<value>.*)")
306
400
 
 
401
        stack = []
307
402
        output = self.stream.read()
308
403
        for record in output.split("\n\n"):
 
404
            record = record.strip()
309
405
            if not record:
310
406
                continue
311
407
 
313
409
            path = None
314
410
            environment = {}
315
411
            for line in record.split("\n"):
316
 
                if not line:
317
 
                    continue
318
 
 
319
412
                match = line_pattern.match(line)
320
413
                if not match:
321
414
                    raise Exception(
333
426
                            "Device property not supported: %s" % value)
334
427
                    environment[match.group("key")] = match.group("value")
335
428
 
 
429
            # Update stack
 
430
            while stack:
 
431
                if stack[-1].path + "/" in path:
 
432
                    break
 
433
                stack.pop()
 
434
 
336
435
            # Set default DEVPATH
337
436
            environment.setdefault("DEVPATH", path)
338
437
 
339
 
            device = self.device_factory(environment)
 
438
            device = self.device_factory(environment, list(stack))
340
439
            if not self._ignoreDevice(device):
341
440
                result.addDevice(device)
 
441
 
 
442
            stack.append(device)