merge with master
[platform/upstream/hplip.git] / check.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 #
4 # (c) Copyright 2003-2009 Hewlett-Packard Development Company, L.P.
5 #
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
10 #
11 # This program 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 this program; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 #
20 # Author: Don Welch
21 #
22
23 __version__ = '14.3'
24 __title__ = 'Dependency/Version Check Utility'
25 __mod__ = 'hp-check'
26 __doc__ = """Check the existence and versions of HPLIP dependencies. (Run as 'python ./check.py' from the HPLIP tarball before installation.)"""
27
28 # Std Lib
29 import sys
30 import os
31 import getopt
32 import commands
33 import re
34
35 # Local
36 from base.g import *
37 from base import utils, tui, models
38 from installer import dcheck
39 from installer.core_install import *
40
41 device_avail = False
42 try:
43     from base import device, pml
44     # This can fail due to hpmudext not being present
45 except ImportError:
46     log.debug("Device library is not avail.")
47 else:
48     device_avail = True
49
50
51 USAGE = [(__doc__, "", "name", True),
52          ("Usage: %s [OPTIONS]" % __mod__, "", "summary", True),
53          utils.USAGE_OPTIONS,
54          ("Compile-time check:", "-c or --compile", "option", False),
55          ("Run-time check:", "-r or --run", "option", False),
56          ("Compile and run-time checks:", "-b or --both (default)", "option", False),
57          utils.USAGE_LOGGING1, utils.USAGE_LOGGING2, utils.USAGE_LOGGING3,
58          utils.USAGE_LOGGING_PLAIN,
59          utils.USAGE_HELP,
60          utils.USAGE_NOTES,
61          ("1. For checking for the proper build environment for the HPLIP supplied tarball (.tar.gz or .run),", "", "note", False),
62          ("use the --compile or --both switches.", "", "note", False),
63          ("2. For checking for the proper runtime environment for a distro supplied package (.deb, .rpm, etc),", "", "note", False),
64          ("use the --runtime switch.", "", "note", False),
65         ]
66
67 def usage(typ='text'):
68     if typ == 'text':
69         utils.log_title(__title__, __version__)
70
71     utils.format_text(USAGE, typ, __title__, __mod__, __version__)
72     sys.exit(0)
73
74
75 build_str = "HPLIP will not build, install, and/or function properly without this dependency."
76
77 pat_deviceuri = re.compile(r"""(.*):/(.*?)/(\S*?)\?(?:serial=(\S*)|device=(\S*)|ip=(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}[^&]*)|zc=(\S+))(?:&port=(\d))?""", re.I)
78 #pat_deviceuri = re.compile(r"""(.*):/(.*?)/(\S*?)\?(?:serial=(\S*)|device=(\S*)|ip=(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}[^&]*))(?:&port=(\d))?""", re.I)
79
80 pat_cups_error_log = re.compile("""^loglevel\s?(debug|debug2|warn|info|error|none)""", re.I)
81
82
83 def parseDeviceURI(device_uri):
84     m = pat_deviceuri.match(device_uri)
85
86     if m is None:
87         raise Error(ERROR_INVALID_DEVICE_URI)
88
89     back_end = m.group(1).lower() or ''
90     is_hp = (back_end in ('hp', 'hpfax', 'hpaio'))
91     bus = m.group(2).lower() or ''
92
93     if bus not in ('usb', 'net', 'bt', 'fw', 'par'):
94         raise Error(ERROR_INVALID_DEVICE_URI)
95
96     model = m.group(3) or ''
97     serial = m.group(4) or ''
98     dev_file = m.group(5) or ''
99     host = m.group(6) or ''
100     zc = ''
101     if not host:
102         zc = host = m.group(7) or ''
103     port = m.group(8) or 1
104
105     if bus == 'net':
106         try:
107             port = int(port)
108         except (ValueError, TypeError):
109             port = 1
110
111         if port == 0:
112             port = 1
113
114 #   log.debug("%s: back_end '%s' is_hp '%s' bus '%s' model '%s' serial '%s' dev_file '%s' host '%s' zc '%s' port '%s' " %
115 #       (device_uri, back_end, is_hp, bus, model, serial, dev_file, host, zc, port))
116
117     return back_end, is_hp, bus, model, serial, dev_file, host, zc, port
118
119 num_errors = 0
120 fmt = True
121 overall_commands_to_run = []
122 time_flag = DEPENDENCY_RUN_AND_COMPILE_TIME
123
124 try:
125     log.set_module(__mod__)
126
127     try:
128         opts, args = getopt.getopt(sys.argv[1:], 'hl:gtcrb',
129             ['help', 'help-rest', 'help-man', 'help-desc', 'logging=',
130              'run', 'runtime', 'compile', 'both'])
131
132     except getopt.GetoptError, e:
133         log.error(e.msg)
134         usage()
135         sys.exit(1)
136
137     if os.getenv("HPLIP_DEBUG"):
138         log.set_level('debug')
139
140     log_level = 'info'
141
142     for o, a in opts:
143         if o in ('-h', '--help'):
144             usage()
145
146         elif o == '--help-rest':
147             usage('rest')
148
149         elif o == '--help-man':
150             usage('man')
151
152         elif o == '--help-desc':
153             print __doc__,
154             sys.exit(0)
155
156         elif o in ('-l', '--logging'):
157             log_level = a.lower().strip()
158
159         elif o == '-g':
160             log_level = 'debug'
161
162         elif o == '-t':
163             fmt = False
164
165         elif o in ('-c', '--compile'):
166             time_flag = DEPENDENCY_COMPILE_TIME
167
168         elif o in ('-r', '--runtime', '--run'):
169             time_flag = DEPENDENCY_RUN_TIME
170
171         elif o in ('-b', '--both'):
172             time_flag = DEPENDENCY_RUN_AND_COMPILE_TIME
173
174     if not log.set_level(log_level):
175         usage()
176
177     if not fmt:
178         log.no_formatting()
179
180     utils.log_title(__title__, __version__)
181
182     log.info(log.bold("Note: hp-check can be run in three modes:"))
183
184     for l in tui.format_paragraph("1. Compile-time check mode (-c or --compile): Use this mode before compiling the HPLIP supplied tarball (.tar.gz or .run) to determine if the proper dependencies are installed to successfully compile HPLIP."):
185         log.info(l)
186
187     for l in tui.format_paragraph("2. Run-time check mode (-r or --run): Use this mode to determine if a distro supplied package (.deb, .rpm, etc) or an already built HPLIP supplied tarball has the proper dependencies installed to successfully run."):
188         log.info(l)
189
190     for l in tui.format_paragraph("3. Both compile- and run-time check mode (-b or --both) (Default): This mode will check both of the above cases (both compile- and run-time dependencies)."):
191         log.info(l)
192
193     log.info()
194
195     log_file = os.path.normpath('./hp-check.log')
196     log.info(log.bold("Saving output in log file: %s" % log_file))
197     log.debug("Log file=%s" % log_file)
198     if os.path.exists(log_file):
199         os.remove(log_file)
200
201     log.set_logfile(log_file)
202     log.set_where(log.LOG_TO_CONSOLE_AND_FILE)
203
204     log.info("\nInitializing. Please wait...")
205     core =  CoreInstall(MODE_CHECK)
206     core.init()
207     core.set_plugin_version()
208
209     tui.header("SYSTEM INFO")
210
211     log.info(log.bold("Basic system information:"))
212     log.info(core.sys_uname_info)
213
214     log.info()
215     log.info(log.bold("Distribution:"))
216     log.info("%s %s" % (core.distro_name, core.distro_version))
217
218     #log.info(log.bold("\nHPOJ running?"))
219
220     #if core.hpoj_present:
221         #log.error("Yes, HPOJ is running. HPLIP is not compatible with HPOJ. To run HPLIP, please remove HPOJ.")
222         #num_errors += 1
223     #else:
224         #log.info("No, HPOJ is not running (OK).")
225
226
227     log.info()
228     log.info(log.bold("Checking Python version..."))
229     ver = sys.version_info
230     log.debug("sys.version_info = %s" % repr(ver))
231     ver_maj = ver[0]
232     ver_min = ver[1]
233     ver_pat = ver[2]
234
235     if ver_maj == 2:
236         if ver_min >= 1:
237             log.info("OK, version %d.%d.%d installed" % ver[:3])
238         else:
239             log.error("Version %d.%d.%d installed. Please update to Python >= 2.1" % ver[:3])
240             sys.exit(1)
241
242     ui_toolkit = sys_conf.get('ui_toolkit', 'qt4')
243     if  ui_toolkit == 'qt3':
244         log.info()
245         log.info(log.bold("Checking PyQt 3.x version..."))
246
247         # PyQt 3
248         try:
249             import qt
250         except ImportError:
251             num_errors += 1
252             log.error("NOT FOUND OR FAILED TO LOAD!")
253         else:
254             # check version of Qt
255             qtMajor = int(qt.qVersion().split('.')[0])
256
257             if qtMajor < MINIMUM_QT_MAJOR_VER:
258                 log.error("Incorrect version of Qt installed. Ver. 3.0.0 or greater required.")
259             else:
260                 #check version of PyQt
261                 try:
262                     pyqtVersion = qt.PYQT_VERSION_STR
263                 except AttributeError:
264                     pyqtVersion = qt.PYQT_VERSION
265
266                 while pyqtVersion.count('.') < 2:
267                     pyqtVersion += '.0'
268
269                 (maj_ver, min_ver, pat_ver) = pyqtVersion.split('.')
270
271                 if pyqtVersion.find('snapshot') >= 0:
272                     log.error("A non-stable snapshot version of PyQt is installed (%s)." % pyqtVersion)
273                     num_errors += 1
274                 else:
275                     try:
276                         maj_ver = int(maj_ver)
277                         min_ver = int(min_ver)
278                         pat_ver = int(pat_ver)
279                     except ValueError:
280                         maj_ver, min_ver, pat_ver = 0, 0, 0
281
282                     if maj_ver < MINIMUM_PYQT_MAJOR_VER or \
283                         (maj_ver == MINIMUM_PYQT_MAJOR_VER and min_ver < MINIMUM_PYQT_MINOR_VER):
284                         num_errors += 1
285                         log.error("HPLIP may not function properly with the version of PyQt that is installed (%d.%d.%d)." % (maj_ver, min_ver, pat_ver))
286                         log.error("Ver. %d.%d or greater required." % (MINIMUM_PYQT_MAJOR_VER, MINIMUM_PYQT_MINOR_VER))
287                     else:
288                         log.info("OK, version %d.%d installed." % (maj_ver, min_ver))
289             del qt
290
291
292     else:
293
294         log.info()
295         log.info(log.bold("Checking PyQt 4.x version..."))
296
297         # PyQt 4
298         try:
299             import PyQt4
300         except ImportError:
301             num_errors += 1
302             log.error("NOT FOUND OR FAILED TO LOAD!")
303         else:
304             from PyQt4 import QtCore
305             log.info("OK, version %s installed." % QtCore.PYQT_VERSION_STR)
306
307
308 #    log.info()
309 #    log.info(log.bold("Checking SIP version..."))
310 #
311 #    sip_ver = None
312 #    try:
313 #        import pyqtconfig
314 #    except ImportError:
315 #        pass
316 #    else:
317 #        sip_ver = pyqtconfig.Configuration().sip_version_str
318 #
319 #    if sip_ver is not None:
320 #        log.info("OK, Version %s installed" % sip_ver)
321 #    else:
322 #        num_errors += 1
323 #        log.error("SIP not installed or version not found.")
324
325     log.info()
326     log.info(log.bold("Checking for CUPS..."))
327     cups_ok = True
328
329     status, output = utils.run('lpstat -r')
330     if status == 0:
331         log.info("Status: %s" % output.strip())
332     else:
333         log.error("Status: (Not available. CUPS may not be installed or not running.)")
334         cups_ok = False
335         num_errors += 1
336
337     if cups_ok:
338         status, output = utils.run('cups-config --version')
339         if status == 0:
340             log.info("Version: %s" % output.strip())
341         else:
342             log.warn("Version: (cups-config) Not available. Unable to determine installed version of CUPS.)")
343
344     if cups_ok:
345         cups_conf = '/etc/cups/cupsd.conf'
346
347         try:
348             f = file(cups_conf, 'r')
349         except (IOError, OSError):
350             log.warn("%s file not found or not accessible." % cups_conf)
351         else:
352             for l in f:
353                 m = pat_cups_error_log.match(l)
354                 if m is not None:
355                     level = m.group(1).lower()
356                     log.info("error_log is set to level: %s" % level)
357
358                     #if level not in ('debug', 'debug2'):
359                         #log.note("For troubleshooting printing issues, it is best to have the CUPS 'LogLevel'")
360                         #log.note("set to 'debug'. To set the LogLevel to debug, edit the file %s (as root)," % cups_conf)
361                         #log.note("and change the line near the top of the file that begins with 'LogLevel' to read:")
362                         #log.note("LogLevel debug")
363                         #log.note("Save the file and then restart CUPS (see your OS/distro docs on how to restart CUPS).")
364                         #log.note("Now, when you print, helpful debug information will be saved to the file:")
365                         #log.note("/var/log/cups/error_log")
366                         #log.note("You can monitor this file by running this command in a console/shell:")
367                         #log.note("tail -f /var/log/cups/error_log")
368
369                     break
370
371
372     log.info()
373
374     log.info(log.bold("Checking for dbus/python-dbus..."))
375
376     if dcheck.check_ps(['dbus-daemon']):
377         log.info("dbus daemon is running.")
378     else:
379         log.warn("dbus daemon is not running.")
380
381     try:
382         import dbus
383         try:
384             log.info("python-dbus version: %s" % dbus.__version__)
385         except AttributeError:
386             try:
387                 log.info("python-dbus version: %s" % '.'.join([str(x) for x in dbus.version]))
388             except AttributeError:
389                 log.warn("python-dbus imported OK, but unknown version.")
390     except ImportError:
391         log.warn("python-dbus not installed.")
392
393     log.info()
394
395
396     if time_flag == DEPENDENCY_RUN_AND_COMPILE_TIME:
397         tui.header("COMPILE AND RUNTIME DEPENDENCIES")
398         log.note("To check for compile-time only dependencies, re-run hp-check with the -c parameter (ie, hp-check -c).")
399         log.note("To check for run-time only dependencies, re-run hp-check with the -r parameter (ie, hp-check -r).")
400
401     elif time_flag == DEPENDENCY_COMPILE_TIME:
402         tui.header("COMPILE TIME DEPENDENCIES")
403
404     elif time_flag == DEPENDENCY_RUN_TIME:
405         tui.header("RUNTIME DEPENDENCIES")
406
407     log.info()
408
409     dd = core.dependencies.keys()
410
411     status, output = utils.run('cups-config --version')
412     import string
413     if status == 0 and (string.count(output, '.') == 1 or string.count(output, '.') == 2):
414         if string.count(output, '.') == 1:
415             major, minor = string.split(output, '.', 2)
416         if string.count(output, '.') == 2:
417             major, minor, release = string.split(output, '.', 3)
418         if len(minor) > 1 and minor[1] >= '0' and minor[1] <= '9':
419             minor = ((ord(minor[0]) - ord('0')) * 10) + (ord(minor[1]) - ord('0'))
420         else:
421             minor = ord(minor[0]) - ord('0')
422         if major > '1' or (major == '1' and minor >= 4):
423             dd.remove('cups-ddk')
424
425     dd.sort()
426     for d in dd:
427         if (d == 'pyqt' and ui_toolkit != 'qt3') or \
428            (d == 'pyqt4' and ui_toolkit != 'qt4'):
429             continue
430
431         log.debug("***")
432
433         if time_flag == DEPENDENCY_RUN_AND_COMPILE_TIME or time_flag == core.dependencies[d][4]:
434
435             log.info(log.bold("Checking for dependency: %s..." % core.dependencies[d][2]))
436
437             if core.have_dependencies[d]:
438                 log.info("OK, found.")
439             else:
440                 num_errors += 1
441
442                 if core.dependencies[d][4] == DEPENDENCY_RUN_AND_COMPILE_TIME:
443                     s = ''
444                 elif core.dependencies[d][4] == DEPENDENCY_COMPILE_TIME:
445                     s = '/COMPILE TIME ONLY'
446
447                 elif core.dependencies[d][4] == DEPENDENCY_RUN_TIME:
448                     s = '/RUNTIME ONLY'
449
450                 if core.dependencies[d][0]:
451                     log.error("NOT FOUND! This is a REQUIRED%s dependency. Please make sure that this dependency is installed before installing or running HPLIP." % s)
452                 else:
453                     log.warn("NOT FOUND! This is an OPTIONAL%s dependency. Some HPLIP functionality may not function properly." %s)
454
455                 if core.distro_supported():
456                     packages_to_install, commands = core.get_dependency_data(d)
457
458                     commands_to_run = []
459
460                     if packages_to_install:
461                         package_mgr_cmd = core.get_distro_data('package_mgr_cmd')
462
463                         if package_mgr_cmd:
464                             packages_to_install = ' '.join(packages_to_install)
465                             commands_to_run.append(utils.cat(package_mgr_cmd))
466
467                     if commands:
468                         commands_to_run.extend(commands)
469
470                     overall_commands_to_run.extend(commands_to_run)
471
472                     if len(commands_to_run) == 1:
473                         log.info("To install this dependency, execute this command:")
474                         log.info(commands_to_run[0])
475
476                     elif len(commands_to_run) > 1:
477                         log.info("To install this dependency, execute these commands:")
478                         for c in commands_to_run:
479                             log.info(c)
480
481
482             log.info()
483
484     if time_flag in (DEPENDENCY_RUN_TIME, DEPENDENCY_RUN_AND_COMPILE_TIME):
485         tui.header("HPLIP INSTALLATION")
486
487         scanning_enabled = utils.to_bool(sys_conf.get('configure', 'scanner-build', '0'))
488
489         log.info()
490         log.info(log.bold("Currently installed HPLIP version..."))
491         v = sys_conf.get('hplip', 'version')
492         home = sys_conf.get('dirs', 'home')
493
494         if v:
495             log.info("HPLIP %s currently installed in '%s'." % (v, home))
496
497             log.info()
498             log.info(log.bold("Current contents of '/etc/hp/hplip.conf' file:"))
499             try:
500                 output = file('/etc/hp/hplip.conf', 'r').read()
501             except (IOError, OSError), e:
502                 log.error("Could not access file: %s" % e.strerror)
503             else:
504                 log.info(output)
505
506             log.info()
507             log.info(log.bold("Current contents of '/var/lib/hp/hplip.state' file:"))
508             try:
509                 output = file(os.path.expanduser('/var/lib/hp/hplip.state'), 'r').read()
510             except (IOError, OSError), e:
511                 log.info("Plugins are not installed. Could not access file: %s" % e.strerror)
512             else:
513                 log.info(output)
514
515             log.info()
516             log.info(log.bold("Current contents of '~/.hplip/hplip.conf' file:"))
517             try:
518                 output = file(os.path.expanduser('~/.hplip/hplip.conf'), 'r').read()
519             except (IOError, OSError), e:
520                 log.error("Could not access file: %s" % e.strerror)
521             else:
522                 log.info(output)
523
524         else:
525             log.info("Not found.")
526
527
528         if device_avail:
529             #if prop.par_build:
530                 #tui.header("DISCOVERED PARALLEL DEVICES")
531
532                 #devices = device.probeDevices(['par'])
533
534                 #if devices:
535                     #f = tui.Formatter()
536                     #f.header = ("Device URI", "Model")
537
538                     #for d, dd in devices.items():
539                         #f.add((d, dd[0]))
540
541                     #f.output()
542
543                 #else:
544                     #log.info("No devices found.")
545
546                     #if not core.have_dependencies['ppdev']:
547                         #log.error("'ppdev' kernel module not loaded.")
548
549             if prop.usb_build:
550                 tui.header("DISCOVERED USB DEVICES")
551
552                 devices = device.probeDevices(['usb'])
553
554                 if devices:
555                     f = tui.Formatter()
556                     f.header = ("Device URI", "Model")
557
558                     for d, dd in devices.items():
559                         f.add((d, dd[0]))
560
561                     f.output()
562
563                 else:
564                     log.info("No devices found.")
565
566
567         tui.header("INSTALLED CUPS PRINTER QUEUES")
568
569         lpstat_pat = re.compile(r"""(\S*): (.*)""", re.IGNORECASE)
570         status, output = utils.run('lpstat -v')
571         log.info()
572
573         cups_printers = []
574         for p in output.splitlines():
575             try:
576                 match = lpstat_pat.search(p)
577                 printer_name = match.group(1)
578                 device_uri = match.group(2)
579                 cups_printers.append((printer_name, device_uri))
580             except AttributeError:
581                 pass
582
583         log.debug(cups_printers)
584
585         if cups_printers:
586             #non_hp = False
587             for p in cups_printers:
588                 printer_name, device_uri = p
589
590                 if device_uri.startswith("cups-pdf:/") or \
591                     device_uri.startswith('ipp://'):
592                     continue
593
594                 try:
595                     back_end, is_hp, bus, model, serial, dev_file, host, zc, port = \
596                         parseDeviceURI(device_uri)
597                 except Error:
598                     back_end, is_hp, bus, model, serial, dev_file, host, zc, port = \
599                         '', False, '', '', '', '', '', '', 1
600
601                 #print back_end, is_hp, bus, model, serial, dev_file, host, zc, port
602
603                 log.info(log.bold(printer_name))
604                 log.info(log.bold('-'*len(printer_name)))
605
606                 x = "Unknown"
607                 if back_end == 'hpfax':
608                     x = "Fax"
609                 elif back_end == 'hp':
610                     x = "Printer"
611
612                 log.info("Type: %s" % x)
613
614                 #if is_hp:
615                 #    x = 'Yes, using the %s: CUPS backend.' % back_end
616                 #else:
617                 #    x = 'No, not using the hp: or hpfax: CUPS backend.'
618                 #    non_hp = True
619
620                 #log.info("Installed in HPLIP?: %s" % x)
621                 log.info("Device URI: %s" % device_uri)
622
623                 ppd = os.path.join('/etc/cups/ppd', printer_name + '.ppd')
624
625                 if os.path.exists(ppd):
626                     log.info("PPD: %s" % ppd)
627                     nickname_pat = re.compile(r'''\*NickName:\s*\"(.*)"''', re.MULTILINE)
628
629                     f = file(ppd, 'r').read(4096)
630
631                     try:
632                         desc = nickname_pat.search(f).group(1)
633                     except AttributeError:
634                         desc = ''
635
636                     log.info("PPD Description: %s" % desc)
637
638                     status, output = utils.run('lpstat -p%s' % printer_name)
639                     log.info("Printer status: %s" % output.replace("\n", ""))
640
641                     if back_end == 'hpfax' and not 'HP Fax' in desc:
642                         num_errors += 1
643                         log.error("Incorrect PPD file for fax queue '%s'. Fax queues must use 'HP-Fax-hplip.ppd'." % printer_name)
644
645                     elif back_end == 'hp' and 'HP Fax' in desc:
646                         num_errors += 1
647                         log.error("Incorrect PPD file for a print queue '%s'. Print queues must not use 'HP-Fax-hplip.ppd'." % printer_name)
648
649                     elif back_end not in ('hp', 'hpfax'):
650                         log.warn("Printer is not HPLIP installed. Printers must use the hp: or hpfax: CUPS backend to function in HPLIP.")
651                         num_errors += 1
652
653                 if device_avail and is_hp:
654                     d = None
655                     try:
656                         try:
657                             d = device.Device(device_uri)
658                         except Error:
659                             log.error("Device initialization failed.")
660                             continue
661
662                         plugin = d.mq.get('plugin', PLUGIN_NONE)
663                         if plugin in (PLUGIN_REQUIRED, PLUGIN_OPTIONAL):
664                             plugin_sts = core.check_for_plugin()
665                             if plugin_sts == PLUGIN_INSTALLED:
666                                 if plugin == PLUGIN_REQUIRED:
667                                     log.info("Required plug-in status: Installed")
668                                 else:
669                                     log.info("Optional plug-in status: Installed")
670                             elif plugin_sts == PLUGIN_VERSION_MISMATCH:
671                                 num_errors += 1
672                                 log.warn("Optional plug-in status: Version mismatch")
673                                 
674                             else:
675                                 num_errors += 1
676                                 if plugin == PLUGIN_REQUIRED:
677                                     log.error("Required plug-in status: Not installed")
678                                 else:
679                                     log.warn("Optional plug-in status: Not installed")
680
681
682                         if bus in ('par', 'usb'):
683                             try:
684                                 d.open()
685                             except Error, e:
686                                 log.error(e.msg)
687                                 deviceid = ''
688                             else:
689                                 deviceid = d.getDeviceID()
690                                 log.debug(deviceid)
691
692                             #print deviceid
693                             if not deviceid:
694                                 log.error("Communication status: Failed")
695                                 #error_code = pml.ERROR_COMMAND_EXECUTION
696                                 num_errors += 1
697                             else:
698                                 log.info("Communication status: Good")
699
700                         elif bus == 'net':
701                             try:
702                                 error_code, deviceid = d.getPML(pml.OID_DEVICE_ID)
703                             except Error:
704                                 #log.error("Communication with device failed.")
705                                 #error_code = pml.ERROR_COMMAND_EXECUTION
706                                 pass
707
708                             #print error_code
709                             if not deviceid:
710                                 log.error("Communication status: Failed")
711                                 num_errors += 1
712                             else:
713                                 log.info("Communication status: Good")
714
715                     finally:
716                         if d is not None:
717                             d.close()
718
719                 log.info()
720
721
722
723         else:
724             log.warn("No queues found.")
725
726         if scanning_enabled:
727             tui.header("SANE CONFIGURATION")
728             log.info(log.bold("'hpaio' in '/etc/sane.d/dll.conf'..."))
729             try:
730                 f = file('/etc/sane.d/dll.conf', 'r')
731             except IOError:
732                 log.error("'/etc/sane.d/dll.conf' not found. Is SANE installed?")
733                 num_errors += 1
734             else:
735                 found = False
736                 for line in f:
737                     lineNoSpace = re.sub(r'\s', '', line) 
738                     hpaiomatched=re.match('hpaio',lineNoSpace)
739 #                   if 'hpaio' in line:
740                     if hpaiomatched:
741                         found = True
742
743                 if found:
744                     log.info("OK, found. SANE backend 'hpaio' is properly set up.")
745                 else:
746                     num_errors += 1
747                     log.error("Not found. SANE backend 'hpaio' NOT properly setup (needs to be added to /etc/sane.d/dll.conf).")
748
749                 log.info()
750                 log.info(log.bold("Checking output of 'scanimage -L'..."))
751                 if utils.which('scanimage'):
752                     status, output = utils.run("scanimage -L")
753                     log.info(output)
754                 else:
755                     log.error("scanimage not found.")
756
757         tui.header("PYTHON EXTENSIONS")
758
759         log.info(log.bold("Checking 'cupsext' CUPS extension..."))
760         try:
761             import cupsext
762         except ImportError:
763             num_errors += 1
764             log.error("NOT FOUND OR FAILED TO LOAD! Please reinstall HPLIP and check for the proper installation of cupsext.")
765         else:
766             log.info("OK, found.")
767
768         log.info()
769         log.info(log.bold("Checking 'pcardext' Photocard extension..."))
770         try:
771             import pcardext
772         except ImportError:
773             num_errors += 1
774             log.error("NOT FOUND OR FAILED TO LOAD! Please reinstall HPLIP and check for the proper installation of pcardext.")
775         else:
776             log.info("OK, found.")
777
778         log.info()
779         log.info(log.bold("Checking 'hpmudext' I/O extension..."))
780         try:
781             import hpmudext
782             hpmudext_avail = True
783         except ImportError:
784             hpmudext_avail = False
785             num_errors += 1
786             log.error("NOT FOUND OR FAILED TO LOAD! Please reinstall HPLIP and check for the proper installation of hpmudext.")
787         else:
788             log.info("OK, found.")
789
790         if scanning_enabled:
791             log.info()
792             log.info(log.bold("Checking 'scanext' SANE scanning extension..."))
793             try:
794                 import scanext
795             except ImportError:
796                 num_errors += 1
797                 log.error("NOT FOUND OR FAILED TO LOAD! Please reinstall HPLIP and check for the proper installation of scanext.")
798             else:
799                 log.info("OK, found.")
800
801                 log.info()
802
803
804         if hpmudext_avail:
805             lsusb = utils.which('lsusb')
806             if lsusb:
807                 log.info()
808
809                 lsusb = os.path.join(lsusb, 'lsusb')
810                 status, output = utils.run("%s -d03f0:" % lsusb)
811
812                 if output:
813                     tui.header("USB I/O SETUP")
814                     log.info(log.bold("Checking for permissions of USB attached printers..."))
815
816                     lsusb_pat = re.compile("""^Bus\s([0-9a-fA-F]{3,3})\sDevice\s([0-9a-fA-F]{3,3}):\sID\s([0-9a-fA-F]{4,4}):([0-9a-fA-F]{4,4})(.*)""", re.IGNORECASE)
817                     log.debug(output)
818
819                     for o in output.splitlines():
820                         ok = True
821                         match = lsusb_pat.search(o)
822
823                         if match is not None:
824                             bus, dev, vid, pid, mfg = match.groups()
825                             log.info("\nHP Device 0x%x at %s:%s: " % (int(pid, 16), bus, dev))
826                             result_code, deviceuri = hpmudext.make_usb_uri(bus, dev)
827
828                             if result_code == hpmudext.HPMUD_R_OK:
829                                 log.info("    Device URI: %s" %  deviceuri)
830                                 d = None
831                                 try:
832                                     d = device.Device(deviceuri)
833                                 except Error:
834                                     continue
835                                 if not d.supported:
836                                     continue
837                             else:
838                                 log.warn("    Device URI: (Makeuri FAILED)")
839                                 continue
840
841                             devnode = os.path.join("/", "dev", "bus", "usb", bus, dev)
842
843                             if not os.path.exists(devnode):
844                                 devnode = os.path.join("/", "proc", "bus", "usb", bus, dev)
845
846                             if os.path.exists(devnode):
847                                 log.info("    Device node: %s" % devnode)
848
849                                 st_mode, st_ino, st_dev, st_nlink, st_uid, st_gid, \
850                                     st_size, st_atime, st_mtime, st_ctime = \
851                                     os.stat(devnode)
852
853                                 log.info("    Mode: 0%o" % (st_mode & 0777))
854
855                                 getfacl = utils.which('getfacl')
856                                 if getfacl:
857                                     getfacl = os.path.join(getfacl, "getfacl")
858
859                                     status, output = utils.run("%s %s" % (getfacl, devnode))
860
861                                     log.info(output)
862
863     tui.header("USER GROUPS")
864
865     groups = utils.which('groups')
866     if groups:
867         groups = os.path.join(groups, 'groups')
868         status, output = utils.run(groups)
869
870         if status == 0:
871             log.info(output)
872
873
874     tui.header("SUMMARY")
875
876     if num_errors:
877         if num_errors == 1:
878             log.error("1 error or warning.")
879         else:
880             log.error("%d errors and/or warnings." % num_errors)
881
882         if overall_commands_to_run:
883             log.info()
884             log.info(log.bold("Summary of needed commands to run to satisfy missing dependencies:"))
885             for c in overall_commands_to_run:
886                 log.info(c)
887
888         log.info()
889         log.info("Please refer to the installation instructions at:")
890         log.info("http://hplip.sourceforge.net/install/index.html\n")
891
892     else:
893         log.info(log.green("No errors or warnings."))
894
895 except KeyboardInterrupt:
896     log.error("User exit")
897
898 log.info()
899 log.info("Done.")
900