2
# -*- coding: utf-8 -*-
4
# (c) Copyright 2003-2009 Hewlett-Packard Development Company, L.P.
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.
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.
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
24
__title__ = 'Dependency/Version Check Utility'
26
__doc__ = """Check the existence and versions of HPLIP dependencies. (Run as 'python ./check.py' from the HPLIP tarball before installation.)"""
37
from base import utils, tui, models
38
from installer import dcheck
39
from installer.core_install import *
43
from base import device, pml
44
# This can fail due to hpmudext not being present
46
log.debug("Device library is not avail.")
51
USAGE = [(__doc__, "", "name", True),
52
("Usage: %s [OPTIONS]" % __mod__, "", "summary", True),
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,
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),
67
def usage(typ='text'):
69
utils.log_title(__title__, __version__)
71
utils.format_text(USAGE, typ, __title__, __mod__, __version__)
75
build_str = "HPLIP will not build, install, and/or function properly without this dependency."
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)
80
pat_cups_error_log = re.compile("""^loglevel\s?(debug|debug2|warn|info|error|none)""", re.I)
83
def parseDeviceURI(device_uri):
84
m = pat_deviceuri.match(device_uri)
87
raise Error(ERROR_INVALID_DEVICE_URI)
89
back_end = m.group(1).lower() or ''
90
is_hp = (back_end in ('hp', 'hpfax', 'hpaio'))
91
bus = m.group(2).lower() or ''
93
if bus not in ('usb', 'net', 'bt', 'fw', 'par'):
94
raise Error(ERROR_INVALID_DEVICE_URI)
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 ''
102
zc = host = m.group(7) or ''
103
port = m.group(8) or 1
108
except (ValueError, TypeError):
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))
117
return back_end, is_hp, bus, model, serial, dev_file, host, zc, port
121
overall_commands_to_run = []
122
time_flag = DEPENDENCY_RUN_AND_COMPILE_TIME
125
log.set_module(__mod__)
128
opts, args = getopt.getopt(sys.argv[1:], 'hl:gtcrb',
129
['help', 'help-rest', 'help-man', 'help-desc', 'logging=',
130
'run', 'runtime', 'compile', 'both'])
132
except getopt.GetoptError, e:
137
if os.getenv("HPLIP_DEBUG"):
138
log.set_level('debug')
143
if o in ('-h', '--help'):
146
elif o == '--help-rest':
149
elif o == '--help-man':
152
elif o == '--help-desc':
156
elif o in ('-l', '--logging'):
157
log_level = a.lower().strip()
165
elif o in ('-c', '--compile'):
166
time_flag = DEPENDENCY_COMPILE_TIME
168
elif o in ('-r', '--runtime', '--run'):
169
time_flag = DEPENDENCY_RUN_TIME
171
elif o in ('-b', '--both'):
172
time_flag = DEPENDENCY_RUN_AND_COMPILE_TIME
174
if not log.set_level(log_level):
180
utils.log_title(__title__, __version__)
182
log.info(log.bold("Note: hp-check can be run in three modes:"))
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."):
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."):
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)."):
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):
201
log.set_logfile(log_file)
202
log.set_where(log.LOG_TO_CONSOLE_AND_FILE)
204
log.info("\nInitializing. Please wait...")
205
core = CoreInstall(MODE_CHECK)
207
core.set_plugin_version()
209
tui.header("SYSTEM INFO")
211
log.info(log.bold("Basic system information:"))
212
log.info(core.sys_uname_info)
215
log.info(log.bold("Distribution:"))
216
log.info("%s %s" % (core.distro_name, core.distro_version))
218
#log.info(log.bold("\nHPOJ running?"))
220
#if core.hpoj_present:
221
#log.error("Yes, HPOJ is running. HPLIP is not compatible with HPOJ. To run HPLIP, please remove HPOJ.")
224
#log.info("No, HPOJ is not running (OK).")
228
log.info(log.bold("Checking Python version..."))
229
ver = sys.version_info
230
log.debug("sys.version_info = %s" % repr(ver))
237
log.info("OK, version %d.%d.%d installed" % ver[:3])
239
log.error("Version %d.%d.%d installed. Please update to Python >= 2.1" % ver[:3])
242
ui_toolkit = sys_conf.get('ui_toolkit', 'qt4')
243
if ui_toolkit == 'qt3':
245
log.info(log.bold("Checking PyQt 3.x version..."))
252
log.error("NOT FOUND OR FAILED TO LOAD!")
254
# check version of Qt
255
qtMajor = int(qt.qVersion().split('.')[0])
257
if qtMajor < MINIMUM_QT_MAJOR_VER:
258
log.error("Incorrect version of Qt installed. Ver. 3.0.0 or greater required.")
260
#check version of PyQt
262
pyqtVersion = qt.PYQT_VERSION_STR
263
except AttributeError:
264
pyqtVersion = qt.PYQT_VERSION
266
while pyqtVersion.count('.') < 2:
269
(maj_ver, min_ver, pat_ver) = pyqtVersion.split('.')
271
if pyqtVersion.find('snapshot') >= 0:
272
log.error("A non-stable snapshot version of PyQt is installed (%s)." % pyqtVersion)
276
maj_ver = int(maj_ver)
277
min_ver = int(min_ver)
278
pat_ver = int(pat_ver)
280
maj_ver, min_ver, pat_ver = 0, 0, 0
282
if maj_ver < MINIMUM_PYQT_MAJOR_VER or \
283
(maj_ver == MINIMUM_PYQT_MAJOR_VER and min_ver < MINIMUM_PYQT_MINOR_VER):
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))
288
log.info("OK, version %d.%d installed." % (maj_ver, min_ver))
295
log.info(log.bold("Checking PyQt 4.x version..."))
302
log.error("NOT FOUND OR FAILED TO LOAD!")
304
from PyQt4 import QtCore
305
log.info("OK, version %s installed." % QtCore.PYQT_VERSION_STR)
309
# log.info(log.bold("Checking SIP version..."))
314
# except ImportError:
317
# sip_ver = pyqtconfig.Configuration().sip_version_str
319
# if sip_ver is not None:
320
# log.info("OK, Version %s installed" % sip_ver)
323
# log.error("SIP not installed or version not found.")
326
log.info(log.bold("Checking for CUPS..."))
329
status, output = utils.run('lpstat -r')
331
log.info("Status: %s" % output.strip())
333
log.error("Status: (Not available. CUPS may not be installed or not running.)")
338
status, output = utils.run('cups-config --version')
340
log.info("Version: %s" % output.strip())
342
log.warn("Version: (cups-config) Not available. Unable to determine installed version of CUPS.)")
345
cups_conf = '/etc/cups/cupsd.conf'
348
f = file(cups_conf, 'r')
349
except (IOError, OSError):
350
log.warn("%s file not found or not accessible." % cups_conf)
353
m = pat_cups_error_log.match(l)
355
level = m.group(1).lower()
356
log.info("error_log is set to level: %s" % level)
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")
374
log.info(log.bold("Checking for dbus/python-dbus..."))
376
if dcheck.check_ps(['dbus-daemon']):
377
log.info("dbus daemon is running.")
379
log.warn("dbus daemon is not running.")
384
log.info("python-dbus version: %s" % dbus.__version__)
385
except AttributeError:
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.")
391
log.warn("python-dbus not installed.")
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).")
401
elif time_flag == DEPENDENCY_COMPILE_TIME:
402
tui.header("COMPILE TIME DEPENDENCIES")
404
elif time_flag == DEPENDENCY_RUN_TIME:
405
tui.header("RUNTIME DEPENDENCIES")
409
dd = core.dependencies.keys()
411
status, output = utils.run('cups-config --version')
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'))
421
minor = ord(minor[0]) - ord('0')
422
if major > '1' or (major == '1' and minor >= 4):
423
dd.remove('cups-ddk')
427
if (d == 'pyqt' and ui_toolkit != 'qt3') or \
428
(d == 'pyqt4' and ui_toolkit != 'qt4'):
433
if time_flag == DEPENDENCY_RUN_AND_COMPILE_TIME or time_flag == core.dependencies[d][4]:
435
log.info(log.bold("Checking for dependency: %s..." % core.dependencies[d][2]))
437
if core.have_dependencies[d]:
438
log.info("OK, found.")
442
if core.dependencies[d][4] == DEPENDENCY_RUN_AND_COMPILE_TIME:
444
elif core.dependencies[d][4] == DEPENDENCY_COMPILE_TIME:
445
s = '/COMPILE TIME ONLY'
447
elif core.dependencies[d][4] == DEPENDENCY_RUN_TIME:
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)
453
log.warn("NOT FOUND! This is an OPTIONAL%s dependency. Some HPLIP functionality may not function properly." %s)
455
if core.distro_supported():
456
packages_to_install, commands = core.get_dependency_data(d)
460
if packages_to_install:
461
package_mgr_cmd = core.get_distro_data('package_mgr_cmd')
464
packages_to_install = ' '.join(packages_to_install)
465
commands_to_run.append(utils.cat(package_mgr_cmd))
468
commands_to_run.extend(commands)
470
overall_commands_to_run.extend(commands_to_run)
472
if len(commands_to_run) == 1:
473
log.info("To install this dependency, execute this command:")
474
log.info(commands_to_run[0])
476
elif len(commands_to_run) > 1:
477
log.info("To install this dependency, execute these commands:")
478
for c in commands_to_run:
484
if time_flag in (DEPENDENCY_RUN_TIME, DEPENDENCY_RUN_AND_COMPILE_TIME):
485
tui.header("HPLIP INSTALLATION")
487
scanning_enabled = utils.to_bool(sys_conf.get('configure', 'scanner-build', '0'))
490
log.info(log.bold("Currently installed HPLIP version..."))
491
v = sys_conf.get('hplip', 'version')
492
home = sys_conf.get('dirs', 'home')
495
log.info("HPLIP %s currently installed in '%s'." % (v, home))
498
log.info(log.bold("Current contents of '/etc/hp/hplip.conf' file:"))
500
output = file('/etc/hp/hplip.conf', 'r').read()
501
except (IOError, OSError), e:
502
log.error("Could not access file: %s" % e.strerror)
507
log.info(log.bold("Current contents of '/var/lib/hp/hplip.state' file:"))
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)
516
log.info(log.bold("Current contents of '~/.hplip/hplip.conf' file:"))
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)
525
log.info("Not found.")
530
#tui.header("DISCOVERED PARALLEL DEVICES")
532
#devices = device.probeDevices(['par'])
536
#f.header = ("Device URI", "Model")
538
#for d, dd in devices.items():
544
#log.info("No devices found.")
546
#if not core.have_dependencies['ppdev']:
547
#log.error("'ppdev' kernel module not loaded.")
550
tui.header("DISCOVERED USB DEVICES")
552
devices = device.probeDevices(['usb'])
556
f.header = ("Device URI", "Model")
558
for d, dd in devices.items():
564
log.info("No devices found.")
567
tui.header("INSTALLED CUPS PRINTER QUEUES")
569
lpstat_pat = re.compile(r"""(\S*): (.*)""", re.IGNORECASE)
570
status, output = utils.run('lpstat -v')
574
for p in output.splitlines():
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:
583
log.debug(cups_printers)
587
for p in cups_printers:
588
printer_name, device_uri = p
590
if device_uri.startswith("cups-pdf:/") or \
591
device_uri.startswith('ipp://'):
595
back_end, is_hp, bus, model, serial, dev_file, host, zc, port = \
596
parseDeviceURI(device_uri)
598
back_end, is_hp, bus, model, serial, dev_file, host, zc, port = \
599
'', False, '', '', '', '', '', '', 1
601
#print back_end, is_hp, bus, model, serial, dev_file, host, zc, port
603
log.info(log.bold(printer_name))
604
log.info(log.bold('-'*len(printer_name)))
607
if back_end == 'hpfax':
609
elif back_end == 'hp':
612
log.info("Type: %s" % x)
615
# x = 'Yes, using the %s: CUPS backend.' % back_end
617
# x = 'No, not using the hp: or hpfax: CUPS backend.'
620
#log.info("Installed in HPLIP?: %s" % x)
621
log.info("Device URI: %s" % device_uri)
623
ppd = os.path.join('/etc/cups/ppd', printer_name + '.ppd')
625
if os.path.exists(ppd):
626
log.info("PPD: %s" % ppd)
627
nickname_pat = re.compile(r'''\*NickName:\s*\"(.*)"''', re.MULTILINE)
629
f = file(ppd, 'r').read(4096)
632
desc = nickname_pat.search(f).group(1)
633
except AttributeError:
636
log.info("PPD Description: %s" % desc)
638
status, output = utils.run('lpstat -p%s' % printer_name)
639
log.info("Printer status: %s" % output.replace("\n", ""))
641
if back_end == 'hpfax' and not 'HP Fax' in desc:
643
log.error("Incorrect PPD file for fax queue '%s'. Fax queues must use 'HP-Fax-hplip.ppd'." % printer_name)
645
elif back_end == 'hp' and 'HP Fax' in desc:
647
log.error("Incorrect PPD file for a print queue '%s'. Print queues must not use 'HP-Fax-hplip.ppd'." % printer_name)
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.")
653
if device_avail and is_hp:
657
d = device.Device(device_uri)
659
log.error("Device initialization failed.")
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")
669
log.info("Optional plug-in status: Installed")
670
elif plugin_sts == PLUGIN_VERSION_MISMATCH:
672
log.warn("Optional plug-in status: Version mismatch")
676
if plugin == PLUGIN_REQUIRED:
677
log.error("Required plug-in status: Not installed")
679
log.warn("Optional plug-in status: Not installed")
682
if bus in ('par', 'usb'):
689
deviceid = d.getDeviceID()
694
log.error("Communication status: Failed")
695
#error_code = pml.ERROR_COMMAND_EXECUTION
698
log.info("Communication status: Good")
702
error_code, deviceid = d.getPML(pml.OID_DEVICE_ID)
704
#log.error("Communication with device failed.")
705
#error_code = pml.ERROR_COMMAND_EXECUTION
710
log.error("Communication status: Failed")
713
log.info("Communication status: Good")
724
log.warn("No queues found.")
727
tui.header("SANE CONFIGURATION")
728
log.info(log.bold("'hpaio' in '/etc/sane.d/dll.conf'..."))
730
f = file('/etc/sane.d/dll.conf', 'r')
732
log.error("'/etc/sane.d/dll.conf' not found. Is SANE installed?")
737
lineNoSpace = re.sub(r'\s', '', line)
738
hpaiomatched=re.match('hpaio',lineNoSpace)
739
# if 'hpaio' in line:
744
log.info("OK, found. SANE backend 'hpaio' is properly set up.")
747
log.error("Not found. SANE backend 'hpaio' NOT properly setup (needs to be added to /etc/sane.d/dll.conf).")
750
log.info(log.bold("Checking output of 'scanimage -L'..."))
751
if utils.which('scanimage'):
752
status, output = utils.run("scanimage -L")
755
log.error("scanimage not found.")
757
tui.header("PYTHON EXTENSIONS")
759
log.info(log.bold("Checking 'cupsext' CUPS extension..."))
764
log.error("NOT FOUND OR FAILED TO LOAD! Please reinstall HPLIP and check for the proper installation of cupsext.")
766
log.info("OK, found.")
769
log.info(log.bold("Checking 'pcardext' Photocard extension..."))
774
log.error("NOT FOUND OR FAILED TO LOAD! Please reinstall HPLIP and check for the proper installation of pcardext.")
776
log.info("OK, found.")
779
log.info(log.bold("Checking 'hpmudext' I/O extension..."))
782
hpmudext_avail = True
784
hpmudext_avail = False
786
log.error("NOT FOUND OR FAILED TO LOAD! Please reinstall HPLIP and check for the proper installation of hpmudext.")
788
log.info("OK, found.")
792
log.info(log.bold("Checking 'scanext' SANE scanning extension..."))
797
log.error("NOT FOUND OR FAILED TO LOAD! Please reinstall HPLIP and check for the proper installation of scanext.")
799
log.info("OK, found.")
805
lsusb = utils.which('lsusb')
809
lsusb = os.path.join(lsusb, 'lsusb')
810
status, output = utils.run("%s -d03f0:" % lsusb)
813
tui.header("USB I/O SETUP")
814
log.info(log.bold("Checking for permissions of USB attached printers..."))
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)
819
for o in output.splitlines():
821
match = lsusb_pat.search(o)
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)
828
if result_code == hpmudext.HPMUD_R_OK:
829
log.info(" Device URI: %s" % deviceuri)
832
d = device.Device(deviceuri)
838
log.warn(" Device URI: (Makeuri FAILED)")
841
devnode = os.path.join("/", "dev", "bus", "usb", bus, dev)
843
if not os.path.exists(devnode):
844
devnode = os.path.join("/", "proc", "bus", "usb", bus, dev)
846
if os.path.exists(devnode):
847
log.info(" Device node: %s" % devnode)
849
st_mode, st_ino, st_dev, st_nlink, st_uid, st_gid, \
850
st_size, st_atime, st_mtime, st_ctime = \
853
log.info(" Mode: 0%o" % (st_mode & 0777))
855
getfacl = utils.which('getfacl')
857
getfacl = os.path.join(getfacl, "getfacl")
859
status, output = utils.run("%s %s" % (getfacl, devnode))
863
tui.header("USER GROUPS")
865
groups = utils.which('groups')
867
groups = os.path.join(groups, 'groups')
868
status, output = utils.run(groups)
874
tui.header("SUMMARY")
878
log.error("1 error or warning.")
880
log.error("%d errors and/or warnings." % num_errors)
882
if overall_commands_to_run:
884
log.info(log.bold("Summary of needed commands to run to satisfy missing dependencies:"))
885
for c in overall_commands_to_run:
889
log.info("Please refer to the installation instructions at:")
890
log.info("http://hplip.sourceforge.net/install/index.html\n")
893
log.info(log.green("No errors or warnings."))
895
except KeyboardInterrupt:
896
log.error("User exit")