1#!/usr/local/bin/python3.8
2# -*- coding: utf-8 -*-
3#
4# (c) Copyright 2003-2015 HP 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, Amarnath Chitumalla
21#
22
23# Std Lib
24import os
25import sys
26import getpass
27import signal
28import re
29
30# Local
31from base.g import *
32from base import utils, tui, os_utils
33from base.sixext import PY3
34from .core_install import *
35from installer import pluginhandler
36
37# Workaround due to incomplete Python3 support in Linux distros.
38PIP_PACKAGE_SEARCH = "PKG_FROM_PIP:"
39Fedora_Py3 = False
40xsane_reg = re.compile(r'\b({0})\b'.format("xsane"))
41bClassPkg = False
42
43
44def progress_callback(cmd="", desc="Working..."):
45    if cmd:
46        log.info("%s (%s)" % (cmd, desc))
47    else:
48        log.info(desc)
49
50
51def option_question_callback(opt, desc, default='y'):
52    ok, ans = tui.enter_yes_no("Do you wish to enable '%s'" % desc, default)
53    if not ok:
54        sys.exit(0)
55    return ans
56
57
58def start(language, auto=True, test_depends=False,
59          test_unknown=False, assume_network=False,
60          max_retries=3, enable=None, disable=None):
61    global bClassPkg
62    try:
63        core = CoreInstall(MODE_INSTALLER, INTERACTIVE_MODE)
64        current_version = prop.installed_version_int
65        log.debug("Currently installed version: 0x%06x" % current_version)
66        core.enable = enable
67        core.disable = disable
68
69        if services.running_as_root():
70            log.error(
71                "You are running the installer as root. It is highly recommended that you run the installer as")
72            log.error("a regular (non-root) user. Do you still wish to continue?")
73
74            ok, ans = tui.enter_yes_no(
75                log.bold("Continue with installation"), 'n')
76            if not ans or not ok:
77                sys.exit(1)
78
79        if auto:
80            log.note(
81                "Running in automatic mode. The most common options will be selected.")
82
83        log.info("")
84        log.note(
85            "Defaults for each question are maked with a '*'. Press <enter> to accept the default.")
86        core.init()
87        vrs = core.get_distro_data('versions_list')
88        Is_Manual_Distro = False
89        distro_alternate_version = None
90        if core.distro_version not in vrs and len(vrs):
91            distro_alternate_version = vrs[len(vrs) - 1]
92            if core.is_auto_installer_support(distro_alternate_version):
93                log.error("%s-%s version is not supported, so all dependencies may not be installed. However trying to install using %s-%s version packages."
94                          % (core.distro_name, core.distro_version, core.distro_name, distro_alternate_version))
95                ok, choice = tui.enter_choice(
96                    "\nPress 'y' to continue auto installation. Press 'n' to quit auto instalation(y=yes, n=no*): ", ['y', 'n'], 'n')
97                if not ok or choice == 'n':
98                    log.info("Installation exit")
99                    sys.exit()
100            else:
101                # Even previous distro is not supported
102                Is_Manual_Distro = True
103        elif not core.is_auto_installer_support():
104              # This distro is not supported
105            Is_Manual_Distro = True
106
107        if Is_Manual_Distro:
108            log.error("Auto installation is not supported for '%s' distro so all dependencies may not be installed. \nPlease install manually as mentioned in 'http://hplipopensource.com/hplip-web/install/manual/index.html' web-site" % core.distro_name)
109            ok, choice = tui.enter_choice(
110                "\nPress 'y' to continue auto installation. Press 'n' to quit auto instalation(y=yes, n=no*): ", ['y', 'n'], 'n')
111            if not ok or choice == 'n':
112                log.info("Installation exit")
113                sys.exit()
114
115        if not auto:
116            tui.title("INSTALLATION MODE")
117            log.info(
118                "Automatic mode will install the full HPLIP solution with the most common options.")
119            log.info(
120                "Custom mode allows you to choose installation options to fit specific requirements.")
121
122            # if os.getenv('DISPLAY') and utils.find_browser() is not None:
123            if 0:
124                ok, choice = tui.enter_choice("\nPlease choose the installation mode (a=automatic*, c=custom, w=web installer, q=quit) : ",
125                                              ['a', 'c', 'w'], 'a')
126            else:
127                ok, choice = tui.enter_choice("\nPlease choose the installation mode (a=automatic*, c=custom, q=quit) : ",
128                                              ['a', 'c'], 'a')
129
130            if not ok:
131                sys.exit(0)
132
133            if choice == 'a':
134                auto = True
135                bClassDriver = False
136                inst_or_pkg_option = 'd'
137                #setup_cmd = './createPPD.sh -q'
138                #if os_utils.execute(setup_cmd) != 0:
139                    #log.error("install Discrete Driver failed")
140
141            elif choice == 'w':
142                from . import web_install
143                log.debug("Starting web browser installer...")
144                web_install.start(language)
145                return
146
147            elif choice == 'c':
148                bClassPkg = False
149                custom = True
150
151        #
152        # HPLIP INSTALLATION
153        #
154        core.selected_component = 'hplip'
155
156        #
157        # INTRODUCTION
158        #
159
160        tui.title("INTRODUCTION")
161        if core.selected_component == 'hplip':
162            log.info(
163                "This installer will install HPLIP version %s on your computer." % core.version_public)
164
165        log.info(
166            "Please close any running package management systems now (YaST, Adept, Synaptic, Up2date, etc).")
167
168        #
169        # CONFIRM AND SELECT DISTRO NAME AND VERSION
170        #
171
172        tui.title("DISTRO/OS CONFIRMATION")
173
174        if core.distro_known():
175            log.info("Distro appears to be %s %s.\n" % (core.get_distro_data(
176                'display_name', '(unknown)'), core.distro_version))
177
178        log.debug("Distro = %s Distro Name = %s Display Name= %s Version = %s Supported = %s" %
179                  (core.distro, core.distro_name, core.distros[core.distro_name]['display_name'],
180                   core.distro_version, core.distro_version_supported))
181
182        distro_ok, ok = False, True
183        if core.distro_known():
184            ok, distro_ok = tui.enter_yes_no('Is "%s %s" your correct distro/OS and version'
185                                             % (core.get_distro_data('display_name', '(unknown)'), core.distro_version))
186
187        if not ok:
188            sys.exit(0)
189
190        if PY3 and core.distro_name.lower() == 'fedora' and int(core.distro_version) < 22:
191            # Workaround due to incomplete Python3 support in Linux distros.
192            global Fedora_Py3
193            Fedora_Py3 = True
194
195        if core.distro_name.lower() == 'manjarolinux':
196            # Workaround to install Manjaro dependency package.
197            log.debug("Installing libidn")
198            if core.distro_version < '18.0':
199                cmd2 = 'sudo pacman -Sy --force --noconfirm libidn'
200            else:
201                cmd2 = 'sudo pacman -Sy --noconfirm libidn'
202            if os_utils.execute(cmd2) != 0:
203                log.warning("Missing ghost script dependency,installation may fail")
204            log.debug("Installing libjpeg-turbo")
205            if core.distro_version < '18.0':
206                cmd = 'sudo pacman -Sy --force --noconfirm libjpeg-turbo'
207            else:
208                cmd = 'sudo pacman -Sy --noconfirm libjpeg-turbo'
209            if os_utils.execute(cmd) != 0:
210                log.warning("Missing libjpeg-turbo dependency,installation may fail")
211            log.debug("Installing ghostscript")
212            if core.distro_version < '18.0':
213                cmd1 = 'sudo pacman -Sy --force --noconfirm ghostscript'
214                if os_utils.execute(cmd1) != 0:
215                    log.warning("Missing ghost script dependency,installation may fail")
216
217        if distro_alternate_version:
218            core.distro_version = distro_alternate_version
219
220        core.distro_changed()
221        if not distro_ok:
222            tui.title("DISTRO/OS SELECTION")
223            core.distro, core.distro_version = DISTRO_UNKNOWN, DISTRO_VER_UNKNOWN
224
225            log.info(log.bold(
226                "\nChoose the name of the distro/OS that most closely matches your system:\n"))
227
228            max_name = 0
229            for d in core.distros_index:
230                dd = core.distros[core.distros_index[d]]
231                if dd['display']:
232                    max_name = max(max_name, len(dd['display_name']))
233
234            formatter = utils.TextFormatter(
235                (
236                    {'width': 4},
237                    {'width': max_name, 'margin': 2},
238                )
239            )
240
241            log.info(formatter.compose(("Num.", "Distro/OS Name")))
242            log.info(formatter.compose(('-' * 4, '-' * (max_name))))
243
244            d_temp = {}
245            x = 0
246            for d in core.distros_index:
247                dd = core.distros[core.distros_index[d]]
248
249                if dd['display']:
250                    d_temp[x] = d
251                    log.info(formatter.compose((str(x), dd['display_name'])))
252                    x += 1
253
254            ok, y = tui.enter_range(
255                "\nEnter number 0...%d (q=quit) ?" % (x - 1), 0, x - 1)
256            if not ok:
257                sys.exit(0)
258
259            core.distro = d_temp[y]
260            core.distro_name = core.distros_index[core.distro]
261            distro_display_name = core.distros[
262                core.distro_name]['display_name']
263            log.debug("Distro = %s Distro Name = %s Display Name= %s" %
264                      (core.distro, core.distro_name, distro_display_name))
265
266            if core.distro != DISTRO_UNKNOWN:
267                versions = list(core.distros[core.distro_name][
268                                'versions'].keys())
269                versions.sort(key=utils.cmp_to_key(cmp))
270
271                log.info(log.bold(
272                    '\nChoose the version of "%s" that most closely matches your system:\n' % distro_display_name))
273                formatter = utils.TextFormatter(
274                    (
275                        {'width': 4},
276                        {'width': 40, 'margin': 2},
277                    )
278                )
279
280                log.info(formatter.compose(("Num.", "Distro/OS Version")))
281                log.info(formatter.compose(('-' * 4, '-' * 40)))
282
283                log.info(formatter.compose(("0", "Unknown or not listed")))
284
285                x = 1
286                for ver in versions:
287                    ver_info = core.distros[core.distro_name]['versions'][ver]
288
289                    if ver_info['code_name'] and ver_info['release_date']:
290                        text = ver + \
291                            ' ("' + ver_info['code_name'] + \
292                            '", Released ' + ver_info['release_date'] + ')'
293
294                    elif ver_info['code_name']:
295                        text = ver + ' ("' + ver_info['code_name'] + '")'
296
297                    elif ver_info['release_date']:
298                        text = ver + ' (Released ' + \
299                            ver_info['release_date'] + ')'
300
301                    else:
302                        text = ver
303
304                    if not ver_info['supported']:
305                        text += " [Unsupported]"
306
307                    log.info(formatter.compose((str(x), text)))
308                    x += 1
309
310                ok, core.distro_version_int = tui.enter_range("\nEnter number 0...%d (q=quit) ?" %
311                                                              (x - 1), 0, x - 1)
312                if not ok:
313                    sys.exit(0)
314
315                if core.distro_version_int == 0:
316                    core.distro_version = DISTRO_VER_UNKNOWN
317                    core.distro_version_supported = False
318                else:
319                    core.distro_version = versions[core.distro_version_int - 1]
320                    core.distro_version_supported = core.get_ver_data(
321                        'supported', False)
322
323                log.debug("Distro = %s Distro Name = %s Display Name= %s Version = %s Supported = %s" %
324                          (core.distro, core.distro_name, core.distros[core.distro_name]['display_name'],
325                           core.distro_version, core.distro_version_supported))
326
327                core.distro_changed()
328
329                log.info("\nDistro set to: %s %s" %
330                         (core.get_distro_data('display_name', '(unknown)'), core.distro_version))
331
332
333# if core.distro == DISTRO_UNKNOWN or not core.distro_version_supported:
334            if core.distro == DISTRO_UNKNOWN:
335                log.error("The distribution/OS that you are running is not supported. This installer\ncannot install an unsupported distribution. Please check your distribution/OS\nand re-run this installer or perform a manual installation.")
336                if num_req_missing:
337                    log.error(
338                        "The following REQUIRED dependencies are missing and need to be installed:")
339
340                    for d, desc, opt in core.missing_required_dependencies():
341                        log.error(
342                            "Missing REQUIRED dependency: %s (%s)" % (d, desc))
343
344                for d, desc, req, opt in core.missing_optional_dependencies():
345                    if req:
346                        log.warning(
347                            "Missing OPTIONAL dependency: %s (%s) [Required for option '%s']" % (d, desc, opt))
348                    else:
349                        log.warning(
350                            "Missing OPTIONAL dependency: %s (%s) [Optional for option '%s']" % (d, desc, opt))
351
352                sys.exit(1)
353
354        if not auto:
355            tui.title("DRIVER OPTIONS")
356            core.distro_name = core.distros_index[core.distro]
357            ok, choice = tui.enter_choice("Would you like to install Custom Discrete Drivers or Class Drivers ( 'd'= Discrete Drivers*,'c'= Class Drivers,'q'= Quit)?   : ",
358                                          ['c', 'd', 'q'], 'd')
359            if not ok or choice == 'q':
360                log.error("User Exit")
361                sys.exit(0)
362
363            if ok and choice == 'c':
364                # bClassDriver is flag will set, when user selects to install
365                # Class Drivers.
366                bClassDriver = True
367                core.selected_options['prnt'] = True
368                core.selected_options['base'] = False
369                core.selected_options['network'] = False
370                core.selected_options['gui_qt4'] = False
371                core.selected_options['gui_qt5'] = False
372                core.selected_options['gui_qt'] = False
373                core.selected_options['fax'] = False
374                core.selected_options['scan'] = False
375                core.selected_options['docs'] = True
376
377                #setup_cmd = './createPPD.sh -f'
378                #if os_utils.execute(setup_cmd) != 0:
379                    #log.error("install Class Driver failed")
380                log.info("")
381                ok, choice = tui.enter_choice(
382                    "Would you like to Create package or Install Class Drivers ('p'=create package, 'i'= install*) : ", ['p', 'i'], 'i')
383                if ok and choice == 'i':
384                    inst_or_pkg_option = 'i'
385
386                elif ok and choice == 'p':
387                    tui.title("Package Generation")
388                    bClassPkg = True
389
390                    if core.distro_name in ['ubuntu', 'debian', 'linuxmint']:
391                        ok, choice = tui.enter_choice(
392                            "Which package would you like to create('t'=tar*,'b'=deb,'q'=Quit) : ", ['t', 'b', 'q'], 't')
393                        if not ok or choice == 'q':
394                            log.error("User Exit")
395                            sys.exit(0)
396                        if ok and choice == 't':
397                            inst_or_pkg_option = 't'
398                        elif ok and choice == 'b':
399                            inst_or_pkg_option = 'b'
400
401                    elif core.distro_name in ['rhel', 'fedora', 'suse', 'centos']:
402                        ok, choice = tui.enter_choice(
403                            "Which package would you like to create('t'=tar*,'r'=rpm,'q'=Quit) : ", ['t', 'r', 'q'], 't')
404                        if not ok or choice == 'q':
405                            log.error("User Exit")
406                            sys.exit(0)
407                        if ok and choice == 't':
408                            inst_or_pkg_option = 't'
409                        elif ok and choice == 'r':
410                            inst_or_pkg_option = 'r'
411                    else:
412                        ok, choice = tui.enter_choice(
413                            "Would you like to create tar package or Quit ('t'=tar*,'q'=Quit) : ", ['t', 'q'], 't')
414                        if not ok or choice == 'q':
415                            log.error("User Exit")
416                            sys.exit(0)
417                        if ok and choice == 't':
418                            inst_or_pkg_option = 't'
419
420            elif ok and choice == 'd':
421                bClassDriver = False
422                inst_or_pkg_option = 'd'
423                #setup_cmd = './createPPD.sh -q'
424                #if os_utils.execute(setup_cmd) != 0:
425                    #log.error("install Discrete Driver failed")
426
427                # installerchanges-end
428
429        log.info("\nInitializing. Please wait...")
430        prev_hplip_version = sys_conf.get("hplip", "version", "0.0.0")
431        pluginObj = pluginhandler.PluginHandle()
432        prev_hplip_plugin_status = pluginObj.getStatus()
433
434        if test_unknown:
435            core.distro_name = 'unknown'
436            core.distro = 0
437            core.distro_version = 0
438
439        # #
440        # # HPLIP INSTALLATION
441        # #
442        # core.selected_component = 'hplip'
443
444        # #
445        # # INTRODUCTION
446        # #
447
448        # tui.title("INTRODUCTION")
449        # if core.selected_component == 'hplip':
450        #     log.info(
451        #         "This installer will install HPLIP version %s on your computer." % core.version_public)
452
453        # log.info(
454        #     "Please close any running package management systems now (YaST, Adept, Synaptic, Up2date, etc).")
455
456        # For testing, mark all dependencies missing
457        if test_depends:
458            for d in core.have_dependencies:
459                core.have_dependencies[d] = False
460
461        num_req_missing = core.count_num_required_missing_dependencies()
462        num_opt_missing = core.count_num_optional_missing_dependencies()
463
464#         #
465#         # CONFIRM AND SELECT DISTRO NAME AND VERSION
466#         #
467
468#         tui.title("DISTRO/OS CONFIRMATION")
469
470#         if core.distro_known():
471#             log.info("Distro appears to be %s %s.\n" % (core.get_distro_data(
472#                 'display_name', '(unknown)'), core.distro_version))
473
474#         log.debug("Distro = %s Distro Name = %s Display Name= %s Version = %s Supported = %s" %
475#                   (core.distro, core.distro_name, core.distros[core.distro_name]['display_name'],
476#                    core.distro_version, core.distro_version_supported))
477
478#         distro_ok, ok = False, True
479#         if core.distro_known():
480#             ok, distro_ok = tui.enter_yes_no('Is "%s %s" your correct distro/OS and version'
481#                                              % (core.get_distro_data('display_name', '(unknown)'), core.distro_version))
482
483#         if not ok:
484#             sys.exit(0)
485
486#         if PY3 and core.distro_name.lower() == 'fedora' and int(core.distro_version) < 22:
487#             # Workaround due to incomplete Python3 support in Linux distros.
488#             global Fedora_Py3
489#             Fedora_Py3 = True
490
491#         if distro_alternate_version:
492#             core.distro_version = distro_alternate_version
493
494#         core.distro_changed()
495#         if not distro_ok:
496#             tui.title("DISTRO/OS SELECTION")
497#             core.distro, core.distro_version = DISTRO_UNKNOWN, DISTRO_VER_UNKNOWN
498
499#             log.info(log.bold(
500#                 "\nChoose the name of the distro/OS that most closely matches your system:\n"))
501
502#             max_name = 0
503#             for d in core.distros_index:
504#                 dd = core.distros[core.distros_index[d]]
505#                 if dd['display']:
506#                     max_name = max(max_name, len(dd['display_name']))
507
508#             formatter = utils.TextFormatter(
509#                 (
510#                     {'width': 4},
511#                     {'width': max_name, 'margin': 2},
512#                 )
513#             )
514
515#             log.info(formatter.compose(("Num.", "Distro/OS Name")))
516#             log.info(formatter.compose(('-' * 4, '-' * (max_name))))
517
518#             d_temp = {}
519#             x = 0
520#             for d in core.distros_index:
521#                 dd = core.distros[core.distros_index[d]]
522
523#                 if dd['display']:
524#                     d_temp[x] = d
525#                     log.info(formatter.compose((str(x), dd['display_name'])))
526#                     x += 1
527
528#             ok, y = tui.enter_range(
529#                 "\nEnter number 0...%d (q=quit) ?" % (x - 1), 0, x - 1)
530#             if not ok:
531#                 sys.exit(0)
532
533#             core.distro = d_temp[y]
534#             core.distro_name = core.distros_index[core.distro]
535#             distro_display_name = core.distros[
536#                 core.distro_name]['display_name']
537#             log.debug("Distro = %s Distro Name = %s Display Name= %s" %
538#                       (core.distro, core.distro_name, distro_display_name))
539
540#             if core.distro != DISTRO_UNKNOWN:
541#                 versions = list(core.distros[core.distro_name][
542#                                 'versions'].keys())
543#                 versions.sort(key=utils.cmp_to_key(cmp))
544
545#                 log.info(log.bold(
546#                     '\nChoose the version of "%s" that most closely matches your system:\n' % distro_display_name))
547#                 formatter = utils.TextFormatter(
548#                     (
549#                         {'width': 4},
550#                         {'width': 40, 'margin': 2},
551#                     )
552#                 )
553
554#                 log.info(formatter.compose(("Num.", "Distro/OS Version")))
555#                 log.info(formatter.compose(('-' * 4, '-' * 40)))
556
557#                 log.info(formatter.compose(("0", "Unknown or not listed")))
558
559#                 x = 1
560#                 for ver in versions:
561#                     ver_info = core.distros[core.distro_name]['versions'][ver]
562
563#                     if ver_info['code_name'] and ver_info['release_date']:
564#                         text = ver + \
565#                             ' ("' + ver_info['code_name'] + \
566#                             '", Released ' + ver_info['release_date'] + ')'
567
568#                     elif ver_info['code_name']:
569#                         text = ver + ' ("' + ver_info['code_name'] + '")'
570
571#                     elif ver_info['release_date']:
572#                         text = ver + ' (Released ' + \
573#                             ver_info['release_date'] + ')'
574
575#                     else:
576#                         text = ver
577
578#                     if not ver_info['supported']:
579#                         text += " [Unsupported]"
580
581#                     log.info(formatter.compose((str(x), text)))
582#                     x += 1
583
584#                 ok, core.distro_version_int = tui.enter_range("\nEnter number 0...%d (q=quit) ?" %
585#                                                               (x - 1), 0, x - 1)
586#                 if not ok:
587#                     sys.exit(0)
588
589#                 if core.distro_version_int == 0:
590#                     core.distro_version = DISTRO_VER_UNKNOWN
591#                     core.distro_version_supported = False
592#                 else:
593#                     core.distro_version = versions[core.distro_version_int - 1]
594#                     core.distro_version_supported = core.get_ver_data(
595#                         'supported', False)
596
597#                 log.debug("Distro = %s Distro Name = %s Display Name= %s Version = %s Supported = %s" %
598#                           (core.distro, core.distro_name, core.distros[core.distro_name]['display_name'],
599# core.distro_version, core.distro_version_supported))
600
601#                 core.distro_changed()
602
603#                 log.info("\nDistro set to: %s %s" %
604#                          (core.get_distro_data('display_name', '(unknown)'), core.distro_version))
605
606
607# # if core.distro == DISTRO_UNKNOWN or not core.distro_version_supported:
608#             if core.distro == DISTRO_UNKNOWN:
609#                 log.error("The distribution/OS that you are running is not supported. This installer\ncannot install an unsupported distribution. Please check your distribution/OS\nand re-run this installer or perform a manual installation.")
610#                 if num_req_missing:
611#                     log.error(
612#                         "The following REQUIRED dependencies are missing and need to be installed:")
613
614#                     for d, desc, opt in core.missing_required_dependencies():
615#                         log.error(
616#                             "Missing REQUIRED dependency: %s (%s)" % (d, desc))
617
618#                 for d, desc, req, opt in core.missing_optional_dependencies():
619#                     if req:
620#                         log.warning(
621#                             "Missing OPTIONAL dependency: %s (%s) [Required for option '%s']" % (d, desc, opt))
622#                     else:
623#                         log.warning(
624#                             "Missing OPTIONAL dependency: %s (%s) [Optional for option '%s']" % (d, desc, opt))
625
626#                 sys.exit(1)
627
628        # #installer changes-START
629        # if not auto:
630        #            tui.title("DRIVER OPTIONS")
631        #            core.distro_name = core.distros_index[core.distro]
632        #            ok, choice = tui.enter_choice("Would you like to install Custom Discrete Drivers or Class Drivers ( 'd'= Discrete Drivers*,'c'= Class Drivers,'q'= Quit)?   : ",
633        #            ['c', 'd','q'], 'd')
634        #            if not ok or choice=='q':
635        #               log.error("User Exit")
636        #               sys.exit(0)
637
638        #            if ok and choice == 'c':
639        #               bClassDriver=True  # bClassDriver is flag will set, when user selects to install Class Drivers.
640        #               setup_cmd = './createPPD.sh -f'
641        #               if os_utils.execute(setup_cmd) != 0:
642        #                   log.error("install Class Driver failed")
643        #               log.info("")
644        #               ok, choice = tui.enter_choice("Would you like to Create package or Install Class Drivers ('p'=create package, 'i'= install*) : ",['p', 'i'], 'i')
645        #               if ok and choice == 'i':
646        #                     inst_or_pkg_option= 'i';
647
648        #               elif ok and choice == 'p':
649        #                     tui.title("Package Generation")
650        #                     bClassPkg = True
651
652        #                     if core.distro_name in ['ubuntu', 'debian', 'linuxmint']:
653        #                        ok, choice = tui.enter_choice("Which package would you like to create('t'=tar*,'b'=deb,'q'=Quit) : ",['t', 'b','q'], 't')
654        #                        if not ok or choice=='q':
655        #                           log.error("User Exit")
656        #                           sys.exit(0)
657        #                        if ok and choice == 't':
658        #                           inst_or_pkg_option= 't';
659        #                        elif ok and choice == 'b':
660        #                           inst_or_pkg_option= 'b';
661
662        #                     elif core.distro_name in ['rhel', 'fedora', 'suse', 'centos']:
663        #                        ok, choice = tui.enter_choice("Which package would you like to create('t'=tar*,'r'=rpm,'q'=Quit) : ",['t', 'r','q'], 't')
664        #                        if not ok or choice=='q':
665        #                           log.error("User Exit")
666        #                           sys.exit(0)
667        #                        if ok and choice == 't':
668        #                           inst_or_pkg_option= 't';
669        #                        elif ok and choice == 'r':
670        #                           inst_or_pkg_option= 'r';
671        #                     else:
672        #                        ok, choice = tui.enter_choice("Would you like to create tar package or Quit ('t'=tar*,'q'=Quit) : ",['t', 'q'], 't')
673        #                        if not ok or choice=='q':
674        #                           log.error("User Exit")
675        #                           sys.exit(0)
676        #                        if ok and choice == 't':
677        #                           inst_or_pkg_option= 't';
678
679        #            elif ok and choice == 'd':
680        #                 bClassDriver=False
681        #                 inst_or_pkg_option= 'd'
682        #                 setup_cmd = './createPPD.sh -q'
683        #                 if os_utils.execute(setup_cmd) != 0:
684        #                      log.error("install Discrete Driver failed")
685
686        #         #installerchanges-end
687        #
688        # SELECT OPTIONS TO INSTALL
689        #
690
691        if not auto:
692            if not bClassDriver:
693                tui.title("SELECT HPLIP OPTIONS")
694                log.info(
695                    "You can select which HPLIP options to enable. Some options require extra dependencies.")
696                log.info("")
697                num_opt_missing = core.select_options(option_question_callback)
698
699        else:
700            enable_par = False
701            core.selected_options['parallel'] = False
702
703        #
704        # COLLECT SUPERUSER PASSWORD
705        #
706        if not services.running_as_root():
707            if core.passwordObj.getAuthType() == "sudo":
708                tui.title("ENTER USER PASSWORD")
709            else:
710                tui.title("ENTER ROOT/SUPERUSER PASSWORD")
711
712            ok = core.check_password()
713            if not ok:
714                log.error(
715                    "3 incorrect attempts. (or) Insufficient permissions(i.e. try with sudo user).\nExiting.")
716                sys.exit(1)
717
718        if not bClassDriver:
719            # INSTALLATION NOTES
720            #
721
722            if core.is_auto_installer_support(distro_alternate_version):
723                distro_notes = core.get_distro_data('notes', '').strip()
724                ver_notes = core.get_ver_data(
725                    'notes', '', distro_alternate_version).strip()
726
727                if distro_notes or ver_notes:
728                    tui.title("INSTALLATION NOTES")
729
730                    if distro_notes:
731                        log.info(distro_notes)
732
733                    if ver_notes:
734                        log.info(ver_notes)
735
736                    log.info("")
737
738                    if not tui.continue_prompt("Please read the installation notes."):
739                        sys.exit(0)
740
741            sec_package_name, is_sec_installed = core.security_package_status()
742
743            if sec_package_name:
744                tui.title("SECURITY PACKAGES")
745                log.info("%s is installed. " % sec_package_name)
746                log.info(
747                    "%s protects the application from external intrusion attempts making the application secure" % sec_package_name)
748
749                if core.distro_name.lower() == 'fedora' and core.distro_version < '28':
750                    #print("SELinux enabling the 'cups_execmem' boolean ")
751                    cds_cmd  = 'su -c "setsebool -P cups_execmem 1" '
752                    status, output = utils.run(cds_cmd, core.passwordObj)
753                    if status != 0:
754                        log.error("SELinux 'cups_execmem ' Boolean set it '1' failed with status %d" % status)
755                elif core.distro_name.lower() == 'fedora':
756                    #print("SELinux enabling the 'cups_execmem' boolean ")
757                    cds_cmd  = 'sudo setsebool -P cups_execmem 1'
758                    status, output = utils.run(cds_cmd, core.passwordObj)
759                    if status != 0:
760                        log.error("SELinux 'cups_execmem ' Boolean set it '1' failed with status %d" % status)
761
762                ok, answer = tui.enter_yes_no(
763                    "\nWould you like to have this installer install the hplip specific policy/profile")
764                if not ok:
765                    sys.exit(0)
766                elif answer:
767                    if sec_package_name == "SELinux":
768                        core.selinux_install()
769                    core.security_package = sec_package_name
770                else:
771                    pass
772
773        #
774        # PRE-INSTALL COMMANDS
775        #
776        tui.title("RUNNING PRE-INSTALL COMMANDS")
777        # some cmds were run...
778        if core.run_pre_install(progress_callback, distro_alternate_version):
779            num_req_missing = core.count_num_required_missing_dependencies()
780            num_opt_missing = core.count_num_optional_missing_dependencies()
781        log.info("OK")
782
783        #
784        # REQUIRED DEPENDENCIES INSTALL
785        #
786        package_mgr_cmd = core.get_distro_ver_data('package_mgr_cmd')
787        depends_to_install = []
788        depends_to_install_using_pip = []
789
790        if num_req_missing or num_opt_missing:
791            tui.title("MISSING DEPENDENCIES")
792            log.info("Following dependencies are not installed. HPLIP will not work if all REQUIRED dependencies are not installed and some of the HPLIP features will not work if OPTIONAL dependencies are not installed.")
793
794            log.info("%-20s %-20s %-20s" %
795                     ("Package-Name", "Component", "Required/Optional"))
796            for d in core.dependencies:
797                comp_list = core.dependencies[d][1]
798                comp_tuple = [(x, core.selected_options[x]) for x in comp_list if
799                              core.selected_options[x]]
800
801                # if not core.have_dependencies[d] and core.selected_options[core.dependencies[d][1][0]]:
802                #     if core.dependencies[d][0]:
803                #         deptype = "REQUIRED"
804                #     else:
805                #         deptype = "OPTIONAL"
806
807                #     log.info("%-20s %-20s %-20s" %(d,
808                #     core.dependencies[d][1][0], deptype))
809
810                if not core.have_dependencies[d] and comp_tuple and comp_tuple[0][1]:
811                    if core.dependencies[d][0]:
812                        deptype = "REQUIRED"
813                    else:
814                        deptype = "OPTIONAL"
815
816                    log.info("%-20s %-20s %-20s" % (d, comp_tuple[0][0],
817                                                    deptype))
818
819            ok, ans = tui.enter_yes_no(
820                "Do you want to install these missing dependencies")
821            if not ok:
822                sys.exit(0)
823
824            if not ans and num_req_missing:
825                log.error(
826                    "Installation can not continue because all REQUIRED dependencies are not installed.")
827                sys.exit(0)
828
829        if num_req_missing:
830            tui.title("INSTALL MISSING REQUIRED DEPENDENCIES")
831            log.notice(
832                "Installation of dependencies requires an active internet connection.")
833
834            for depend, desc, option in core.missing_required_dependencies():
835                log.warning("Missing REQUIRED dependency: %s (%s)" %
836                            (depend, desc))
837                # Workaround due to incomplete Python3 support in Linux
838                # distros.
839                if Fedora_Py3:
840                    continue
841
842                ok = False
843                packages, commands = core.get_dependency_data(
844                    depend, distro_alternate_version)
845                log.debug("Packages: %s" % ','.join(packages))
846                log.debug("Commands: %s" % ','.join(commands))
847
848#                if core.distro_version_supported and (packages or commands):
849                if package_mgr_cmd and (packages or commands):
850                    if auto:
851                        answer = True
852                    else:
853                        ok, answer = tui.enter_yes_no(
854                            "\nWould you like to have this installer install the missing dependency")
855                        if not ok:
856                            # TBD: TELL CUSTOMER THAT YOU ARE QUITTING
857                            sys.exit(0)
858
859                    if answer:
860                        ok = True
861                        log.debug("Adding '%s' to list of dependencies to install. %s" % (
862                            depend, packages))
863                        # Adding package which requires python(3)-pip package.
864                        for pk in packages:
865                            if PIP_PACKAGE_SEARCH in pk:
866                                depends_to_install_using_pip.append(
867                                    pk.replace(PIP_PACKAGE_SEARCH, ''))
868
869                        depends_to_install.append(depend)
870
871                else:
872                    log.warn(
873                        "This installer cannot install '%s' for your distro/OS and/or version." % depend)
874
875                if not ok:
876                    log.error(
877                        "Installation cannot continue without this dependency. Please manually install this dependency and re-run this installer.")
878                    sys.exit(0)
879
880            # Workaround due to incomplete Python3 support in Linux distros.
881            if Fedora_Py3:
882                log.info("")
883                log.error(
884                    "'yum' tool required for package downloads is not supported for Python 3 environments by Fedora.\nHPLIP installation failed.")
885                log.info("")
886                log.warn(log.bold(
887                    "Manually install the required dependencies to to use HPLIP with Python 3.x on Fedora. More information is available at http://hplipopensource.com/node/369"))
888                log.info("")
889                sys.exit(1)
890
891        #
892        # OPTIONAL dependencies
893        #
894        if num_opt_missing:
895            tui.title("INSTALL MISSING OPTIONAL DEPENDENCIES")
896            log.notice(
897                "Installation of dependencies requires an active internet connection.")
898
899            for depend, desc, required_for_opt, opt in core.missing_optional_dependencies():
900
901                if required_for_opt:
902                    log.warning("Missing REQUIRED dependency for option '%s': %s (%s)" % (
903                        opt, depend, desc))
904
905                else:
906                    log.warning("Missing OPTIONAL dependency for option '%s': %s (%s)" % (
907                        opt, depend, desc))
908
909                if Fedora_Py3:          # Workaround due to incomplete Python3 support in Linux distros.
910                    continue
911
912                installed = False
913                packages, commands = core.get_dependency_data(
914                    depend, distro_alternate_version)
915                log.debug("Packages: %s" % ','.join(packages))
916                log.debug("Commands: %s" % ','.join(commands))
917
918
919#                if core.distro_version_supported and (packages or commands):
920                if package_mgr_cmd and (packages or commands):
921                    if auto:
922                        answer = True
923                    else:
924                        ok, answer = tui.enter_yes_no(
925                            "\nWould you like to have this installer install the missing dependency")
926                        if not ok:
927                            sys.exit(0)
928
929                    if answer:
930                        log.debug("Adding '%s' to list of dependencies to install. %s" % (
931                            depend, packages))
932                        # Adding package which requires python(3)-pip package.
933                        for pk in packages:
934                            if PIP_PACKAGE_SEARCH in pk:
935                                depends_to_install_using_pip.append(
936                                    pk.replace(PIP_PACKAGE_SEARCH, ''))
937
938                        depends_to_install.append(depend)
939
940                    else:
941                        log.warning(
942                            "Missing dependencies may affect the proper functioning of HPLIP. Please manually install this dependency after you exit this installer.")
943                        log.warning(
944                            "Note: Options that have REQUIRED dependencies that are missing will be turned off.")
945
946                        if required_for_opt:
947                            log.warn("Option '%s' has been turned off." % opt)
948                            core.selected_options[opt] = False
949                else:
950                    log.warn(
951                        "This installer cannot install '%s' for your distro/OS and/or version." % depend)
952
953                    if required_for_opt:
954                        log.warn("Option '%s' has been turned off." % opt)
955                        core.selected_options[opt] = False
956
957            # Workaround due to incomplete Python3 support in Linux distros.
958            if Fedora_Py3:
959                log.info("")
960                log.warn(
961                    "'yum' tool required for package downloads is not supported for Python 3 environments by Fedora.")
962                log.warn(
963                    "Missing dependencies may affect the proper functioning of HPLIP")
964                log.info("")
965                log.notice(log.bold(
966                    "Manually install the above missing dependencies if required. More information is available at http://hplipopennsource.com/node/369"))
967                log.info("")
968
969        log.debug("Dependencies to install: %s  hplip_present:%s" %
970                  (depends_to_install, core.hplip_present))
971
972#        if core.distro_version_supported and \
973#            (depends_to_install or core.hplip_present) and \
974#            core.selected_component == 'hplip':
975
976        if package_mgr_cmd and \
977            (depends_to_install or core.hplip_present) and \
978                core.selected_component == 'hplip':
979            #
980            # CHECK FOR RUNNING PACKAGE MANAGER
981            #
982            User_exit, Is_pkg_mgr_running = core.close_package_managers()
983            if User_exit:
984                sys.exit(0)
985#            if Is_pkg_mgr_running:
986#                log.debug("Some Package manager are still running. ")
987
988            #
989            # CHECK FOR ACTIVE NETWORK CONNECTION
990            #
991            if not assume_network:
992                tui.title("CHECKING FOR NETWORK CONNECTION")
993
994                if not utils.check_network_connection():
995                    log.error(
996                        "The network appears to be unreachable. Installation may not resolve all dependencies without access to distribution repositories.")
997                    ok, choice = tui.enter_choice(
998                        "Do you want to continue installation without network?. Press 'y' for YES. Press 'n' for NO (y=yes*, n=no) : ", ['y', 'n'], 'y')
999                    if not ok or choice == 'n':
1000                        log.info("Please connect network and try again")
1001                        sys.exit(1)
1002                    else:
1003                        log.debug("Continuing installation without network")
1004                else:
1005                    log.info("Network connection present.")
1006
1007            # sec_package_name, is_sec_installed = core.security_package_status()
1008
1009            # if sec_package_name:
1010            #     tui.title("SECURITY PACKAGES")
1011            #     log.info("%s is installed. " % sec_package_name)
1012            #     log.info("%s protects the application from external intrusion attempts making the application secure" % sec_package_name )
1013            #     ok, answer = tui.enter_yes_no("\nWould you like to have this installer install the hplip specific policy/profile")
1014            #     if not ok:
1015            #         sys.exit(0)
1016            #     elif answer:
1017            #         core.security_package = sec_package_name
1018            #     else:
1019            #         pass
1020
1021            #
1022            # PRE-DEPEND
1023            #
1024
1025            tui.title("RUNNING PRE-PACKAGE COMMANDS")
1026            # Workaround due to incomplete Python3 support in Linux distros.
1027            if not Fedora_Py3:
1028                core.run_pre_depend(progress_callback,
1029                                    distro_alternate_version)
1030                log.info("OK")
1031
1032            #
1033            # INSTALL PACKAGES AND RUN COMMANDS
1034            #
1035
1036            tui.title("DEPENDENCY AND CONFLICT RESOLUTION")
1037
1038            packages = []
1039            commands_to_run = []
1040            package_mgr_cmd = core.get_distro_ver_data('package_mgr_cmd')
1041
1042            # HACK!
1043            individual_pkgs = True
1044            if package_mgr_cmd.startswith('xterm'):
1045                individual_pkgs = False
1046
1047            if package_mgr_cmd:
1048                log.debug("Preparing to install packages and run commands...")
1049
1050                for d in depends_to_install:
1051                    log.debug("*** Processing dependency: %s" % d)
1052                    pkgs, commands = core.get_dependency_data(
1053                        d, distro_alternate_version)
1054
1055                    if pkgs:
1056                        log.debug("Package(s) '%s' will be installed to satisfy dependency '%s'." %
1057                                  (','.join(pkgs), d))
1058
1059                        packages.extend(pkgs)
1060
1061                    if commands:
1062                        log.debug("Command(s) '%s' will be run to satisfy dependency '%s'." %
1063                                  (','.join(commands), d))
1064
1065                        commands_to_run.extend(commands)
1066
1067            else:
1068                log.error("Invalid package manager")
1069
1070            log.debug("Packages: %s" % packages)
1071            log.debug("Commands: %s" % commands_to_run)
1072            log.debug("Install individual packages: %s" % individual_pkgs)
1073
1074            PY_PIP = False
1075            # Workaround due to incomplete Python3 support in Linux distros.
1076            if len(depends_to_install_using_pip):
1077                if PY3:
1078                    packages_to_install = 'python3-pip'
1079                else:
1080                    packages_to_install = 'python-pip'
1081
1082                cmd = utils.cat(package_mgr_cmd)
1083                log.info(
1084                    "Running '%s'\nPlease wait, this may take several minutes..." % cmd)
1085                status, output = utils.run(cmd, core.passwordObj)
1086                if status != 0:
1087                    log.error(
1088                        "Package install command failed with error code %d" % status)
1089                    log.warn(
1090                        "Some HPLIP functionality might not function due to missing package(s). [%s]" % depends_to_install_using_pip)
1091                    if PY3:          # Workaround due to incomplete Python3 support in Linux distros.
1092                        log.notice(log.bold(
1093                            "More information is available at http://hplipopensource.com/node/369"))
1094                        sys.exit(1)
1095                else:
1096                    PY_PIP = True
1097
1098            if package_mgr_cmd and packages:
1099                if individual_pkgs:
1100                    for packages_to_install in packages:
1101                        if PIP_PACKAGE_SEARCH in packages_to_install:
1102                            # This will be installed using python(3)-pip
1103                            continue
1104
1105                        # Workaround due to incomplete Python3 support in Linux
1106                        # distros.
1107                        xsane_var = PY3 and core.get_distro_data('display_name', '(unknown)') in [
1108                            "Ubuntu", "Linux Mint"]
1109                        retries = 0
1110                        while True:
1111                            cmd = utils.cat(package_mgr_cmd)
1112                            # Workaround due to incomplete Python3 support in
1113                            # Linux distros.
1114                            if xsane_var and xsane_reg.search(cmd):
1115                                package_mgr_cmd_xsane = "sudo apt-get install --no-install-recommends --assume-yes $packages_to_install"
1116                                cmd = utils.cat(package_mgr_cmd_xsane)
1117
1118                            log.debug("Package manager command: %s" % cmd)
1119
1120                            log.info(
1121                                "Running '%s'\nPlease wait, this may take several minutes..." % cmd)
1122                            status, output = utils.run(cmd, core.passwordObj)
1123
1124                            if status != 0:
1125                                retries += 1
1126                                if retries < (max_retries + 1):
1127                                    log.error(
1128                                        "Command failed. Re-try #%d..." % retries)
1129                                    continue
1130
1131                                log.error(
1132                                    "Package install command failed with error code %d" % status)
1133                                if PY3:
1134                                    log.notice(
1135                                        "Some packages may not get installed on python3 due to distro incompatibilites")
1136                                    log.info("")
1137                                    log.notice(
1138                                        "Please check for more information at http://hplipopensource.com/node/369")
1139                                ok, ans = tui.enter_yes_no(
1140                                    "Would you like to retry installing the missing package(s)")
1141
1142                                if not ok:
1143                                    sys.exit(0)
1144
1145                                if ans:
1146                                    continue
1147                                else:
1148                                    log.warn(
1149                                        "Some HPLIP functionality might not function due to missing package(s).")
1150                                    break
1151                            else:
1152                                break
1153
1154                else:
1155                    packages_to_install = ' '.join(packages)
1156                    while True:
1157                        cmd = utils.cat(package_mgr_cmd)
1158                        log.debug("Package manager command: %s" % cmd)
1159
1160                        log.info(
1161                            "Running '%s'\nPlease wait, this may take several minutes..." % cmd)
1162                        status, output = utils.run(cmd, core.passwordObj)
1163
1164                        if status != 0:
1165                            log.error(
1166                                "Package install command failed with error code %d" % status)
1167                            ok, ans = tui.enter_yes_no(
1168                                "Would you like to retry installing the missing package(s)")
1169
1170                            if not ok:
1171                                sys.exit(0)
1172
1173                            if ans:
1174                                continue
1175                            else:
1176                                log.warn(
1177                                    "Some HPLIP functionality might not function due to missing package(s).")
1178                                break
1179                        else:
1180                            break
1181            if PY_PIP:
1182                pip_cmd = utils.find_pip()
1183                if pip_cmd:
1184                    for d in depends_to_install_using_pip:
1185                        cmd = "%s  install %s" % (pip_cmd, d)
1186                        cmd = core.passwordObj.getAuthCmd() % cmd
1187                        log.info(
1188                            "Running '%s'\nPlease wait, this may take several minutes..." % cmd)
1189                        status, output = utils.run(cmd, core.passwordObj)
1190                        if status != 0:
1191                            log.error(
1192                                "Package install command failed with error code %d" % status)
1193                            log.warn(
1194                                "Some HPLIP functionality might not function due to missing package(s). [%s]" % d)
1195
1196            if commands_to_run:
1197                for cmd in commands_to_run:
1198                    log.debug(cmd)
1199                    log.info(
1200                        "Running '%s'\nPlease wait, this may take several minutes..." % cmd)
1201                    status, output = utils.run(cmd, core.passwordObj)
1202
1203                    if status != 0:
1204                        log.error(
1205                            "Install command failed with error code %d" % status)
1206                        sys.exit(1)
1207
1208            #
1209            # HPLIP REMOVE
1210            #
1211            num_req_missing = 0
1212            core.check_dependencies()
1213            for depend, desc, opt in core.missing_required_dependencies():
1214                log.error(
1215                    "A required dependency '%s (%s)' is still missing." % (depend, desc))
1216                num_req_missing += 1
1217
1218            if not bClassPkg and num_req_missing == 0 and core.hplip_present and core.selected_component == 'hplip' and core.distro_version_supported:
1219                path = utils.which('hp-uninstall')
1220                ok, choice = tui.enter_choice(
1221                    "HPLIP-%s exists, this may conflict with the new one being installed.\nDo you want to ('i'= Remove and Install*, 'q'= Quit)?    :" % (prev_hplip_version), ['i', 'q'], 'i')
1222                if not ok or choice == 'q':
1223                    log.error("User Exit")
1224                    sys.exit(0)
1225                elif choice == 'i':
1226                    #                    log.info("Uninstalling existing HPLIP-%s"%prev_hplip_version)
1227                    sts = core.uninstall(NON_INTERACTIVE_MODE)
1228
1229                    if sts is False:
1230                        log.warn(
1231                            "Failed to uninstall existing HPLIP-%s. This installation will overwrite on existing HPLIP" % prev_hplip_version)
1232                    else:
1233                        log.debug("HPLIP-%s is uninstalled successfully." %
1234                                  prev_hplip_version)
1235
1236            #
1237            # POST-DEPEND
1238            #
1239            tui.title("RUNNING POST-PACKAGE COMMANDS")
1240            core.run_post_depend(progress_callback)
1241            log.info("OK")
1242
1243
1244            if core.distro_name.lower() == 'manjarolinux':
1245                # Workaround to install Manjaro dependency package.
1246                log.debug("Installing libidn")
1247                if core.distro_version < '18.0':
1248                    cmd2 = 'sudo pacman -Sy --force --noconfirm libidn'
1249                else:
1250                    cmd2 = 'sudo pacman -Sy --noconfirm libidn'
1251                if os_utils.execute(cmd2) != 0:
1252                    log.warning("Missing ghost script dependency,installation may fail")
1253                log.debug("Installing libjpeg-turbo")
1254                if core.distro_version < '18.0':
1255                    cmd = 'sudo pacman -Sy --force --noconfirm libjpeg-turbo'
1256                else:
1257                    cmd = 'sudo pacman -Sy --noconfirm libjpeg-turbo'
1258                if os_utils.execute(cmd) != 0:
1259                    log.warning("Missing libjpeg-turbo dependency,installation may fail")
1260                log.debug("Installing ghostscript")
1261                if core.distro_version < '18.0':
1262                    cmd1 = 'sudo pacman -Sy --force --noconfirm ghostscript'
1263                    if os_utils.execute(cmd1) != 0:
1264                        log.warning("Missing ghost script dependency,installation may fail")
1265
1266            if core.distro_name.lower() == 'fedora' and core.distro_version >= '30':
1267                cmd_fedora = 'sudo dnf -y -d 10 -e 1 install dbus-devel'
1268                status, output = utils.run(cmd_fedora, core.passwordObj)
1269                if status != 0:
1270                    log.error("Install command failed with error code %d" % status)
1271                    sys.exit(1)
1272
1273            #
1274            # DEPENDENCIES RE-CHECK
1275            #
1276            tui.title("RE-CHECKING DEPENDENCIES")
1277            core.check_dependencies()
1278
1279            num_req_missing = 0
1280            for depend, desc, opt in core.missing_required_dependencies():
1281                num_req_missing += 1
1282                log.error(
1283                    "A required dependency '%s (%s)' is still missing." % (depend, desc))
1284
1285            if num_req_missing:
1286                if num_req_missing > 1:
1287                    log.error(
1288                        "Installation cannot continue without these dependencies.")
1289                else:
1290                    log.error(
1291                        "Installation cannot continue without this dependency.")
1292
1293                log.error(
1294                    "Please manually install this dependency and re-run this installer.")
1295                sys.exit(1)
1296
1297            for depend, desc, required_for_opt, opt in core.missing_optional_dependencies():
1298                if required_for_opt:
1299                    log.warn(
1300                        "An optional dependency '%s (%s)' is still missing." % (depend, desc))
1301                    log.warn("Option '%s' has been turned off." % opt)
1302                    core.selected_options[opt] = False
1303                else:
1304                    log.warn(
1305                        "An optional dependency '%s (%s)' is still missing." % (depend, desc))
1306                    log.warn("Some features may not function as expected.")
1307
1308            if not num_opt_missing and not num_req_missing:
1309                log.info("OK")
1310
1311        #
1312        # SCANJET DEPENDENCIES
1313        #
1314        if bClassDriver == False:
1315            tui.title("RUNNING SCANJET DEPENDENCY COMMANDS")
1316            core.run_scanjet_depend(progress_callback)
1317            log.info("OK")
1318
1319        #
1320        # INSTALL LOCATION
1321        #
1322
1323        log.debug("Install location = %s" % core.install_location)
1324
1325        #
1326        # BUILD AND INSTALL
1327        #
1328
1329        if not auto and not bClassDriver:
1330            tui.title("READY TO BUILD AND INSTALL")
1331            if not tui.continue_prompt("Ready to perform build and install."):
1332                sys.exit(0)
1333
1334        tui.title("PRE-BUILD COMMANDS")
1335        core.run_pre_build(progress_callback, distro_alternate_version)
1336        log.info("OK")
1337
1338        if bClassDriver and bClassPkg:
1339            tui.title("BUILD AND PACKAGE")
1340        else:
1341            tui.title("BUILD AND INSTALL")
1342        os.umask(0o022)
1343        for cmd in core.build_cmds(bClassDriver, inst_or_pkg_option):
1344            log.info(
1345                "Running '%s'\nPlease wait, this may take several minutes..." % cmd)
1346            status, output = utils.run(cmd, core.passwordObj)
1347
1348            if status != 0:
1349                if 'configure' in cmd:
1350                    log.error("Configure failed with error: %s" % (
1351                        CONFIGURE_ERRORS.get(status, CONFIGURE_ERRORS[1])))
1352                    log.error("output = %s" % output)
1353
1354                else:
1355                    log.error("'%s' command failed with status code %d" %
1356                              (cmd, status))
1357
1358                sys.exit(0)
1359            else:
1360                log.info("Command completed successfully.")
1361
1362            log.info("")
1363
1364        if inst_or_pkg_option == 'i' or inst_or_pkg_option == 'd':
1365            log.info("\nBuild complete.")
1366            log.info("")
1367
1368        elif inst_or_pkg_option == 't':
1369            log.info("\nPackage created successfully.")
1370            log.info("\nThe package file is placed in the directory from where the '.run' file has been executed")
1371            log.info("For Eg: If the hplip-x.xx.xx.run file is executed from /home/user/, the package file will be placed in /home/user/hplip-x.xx.xx.internal/ path with file extension of .tar")
1372
1373        elif inst_or_pkg_option == 'b':
1374            log.info("\nPackage created successfully.")
1375            log.info("\nThe package file is placed in the directory from where the '.run' file has been executed")
1376            log.info("For Eg: If the hplip-x.xx.xx.run file is executed from /home/user/, the package file will be placed in /home/user/hplip-x.xx.xx.internal/ path with file extension of .deb")
1377
1378        else:
1379            log.info("\nPackage created successfully.")
1380            log.info("\nThe package file is placed in the directory /home/user/rpmbuild/RPMS/")
1381
1382            # PLUGIN INFO
1383            tui.title("PLUG-IN INFO")
1384            paragraph = "If plugin are not installed, download the plug-ins from fallback location:https://developers.hp.com/hp-linux-imaging-and-printing"
1385
1386            for p in tui.format_paragraph(paragraph):
1387                log.info(p)
1388            log.info("")
1389            exit(0)
1390
1391        #
1392        # POST BUILD
1393        #
1394
1395        tui.title("POST-BUILD COMMANDS")
1396        core.run_post_build(progress_callback, distro_alternate_version)
1397        core.remove_soT()
1398
1399        if not (core.distro_name.lower() == 'manjarolinux'):
1400            try:
1401                from prnt import cups
1402                # This call is just to update the cups PPD cache file@
1403                # /var/cache/cups/ppds.dat. If this is not called, hp-setup picks
1404                # incorrect ppd 1st time for some printers.
1405                cups.getSystemPPDs()
1406            except ImportError:
1407                log.error("Failed to Import Cups")
1408
1409        #
1410        # OPEN MDNS MULTICAST PORT
1411        #
1412        user_conf = UserConfig()
1413
1414        if core.selected_options['network']:
1415            open_mdns_port = core.get_distro_ver_data(
1416                'open_mdns_port', None, distro_alternate_version)
1417            if open_mdns_port:
1418                tui.title(
1419                    "OPEN MDNS/BONJOUR FIREWALL PORT (MULTICAST PORT 5353)")
1420
1421                paragraph = "In order to setup your printer on the network using mDNS/Bonjour, it is required that your internet firewall allows connections on port 5353. If this port is blocked by the firewall, connection to network printers using mDNS/Bonjour will not be possible."
1422
1423                for p in tui.format_paragraph(paragraph):
1424                    log.info(p)
1425                log.info("")
1426
1427                ok, ans = tui.enter_yes_no(
1428                    "Do you wish to open this port on your internet firewall")
1429                if not ok:
1430                    sys.exit(0)
1431
1432                if ans:
1433                    services.run_open_mdns_port(core, core.passwordObj)
1434                else:
1435                    log.warn("Skipping firewall setup. If this port is blocked on your firewall when setting up network printers, use SLP discovery and device URIs with ?ip=x.x.x.x. When using hp-setup, choose 'SLP' discovery under 'Advanced'.")
1436
1437        #
1438        # Try to close running hp-systray (3.9.2 or later)
1439        #
1440
1441        if current_version >= 0x030902:  # 3.9.2
1442            try:
1443                from dbus import SessionBus, lowlevel
1444            except ImportError:
1445                pass
1446            else:
1447                try:
1448                    args = ['', '', EVENT_SYSTEMTRAY_EXIT,
1449                            prop.username, 0, '', '']
1450                    msg = lowlevel.SignalMessage(
1451                        '/', 'com.hplip.StatusService', 'Event')
1452                    msg.append(signature='ssisiss', *args)
1453                    tui.title("CLOSE HP_SYSTRAY")
1454                    log.info(
1455                        "Sending close message to hp-systray (if it is currently running)...")
1456                    SessionBus().send_message(msg)
1457                    time.sleep(0.5)
1458                except:
1459                    pass
1460        log.info("OK")
1461
1462        # If class driver then we need not do the below steps.
1463        if bClassDriver:
1464            log.info(
1465                "More information is available at https://developers.hp.com/hp-linux-imaging-and-printing")
1466            log.info("")
1467            exit(0)
1468
1469        tui.title("HPLIP UPDATE NOTIFICATION")
1470        ok, choice = tui.enter_choice(
1471            "Do you want to check for HPLIP updates?. (y=yes*, n=no) : ", ['y', 'n'], 'y')
1472        if not ok or choice != 'y':
1473            user_conf.set('upgrade', 'notify_upgrade', 'false')
1474        else:
1475            user_conf.set('upgrade', 'notify_upgrade', 'true')
1476
1477        user_conf.set('upgrade', 'last_upgraded_time', str(int(time.time())))
1478        user_conf.set('upgrade', 'pending_upgrade_time', '0')
1479
1480        if prev_hplip_plugin_status != pluginhandler.PLUGIN_NOT_INSTALLED:
1481            tui.title("HPLIP PLUGIN UPDATE NOTIFICATION")
1482            ok, choice = tui.enter_choice(
1483                "HPLIP Plug-in's needs to be installed/updated. Do you want to update plug-in's?. (y=yes*, n=no) : ", ['y', 'n'], 'y')
1484            if ok and choice == 'y':
1485                ok, choice = tui.enter_choice(
1486                    "Do you want to install plug-in's in GUI mode?. (u=GUI mode*, i=Interactive mode) : ", ['u', 'i'], 'u')
1487                if ok and choice == 'u':
1488                    plugin_cmd = 'hp-plugin  -u'
1489                elif ok and choice == 'i':
1490                    plugin_cmd = 'hp-plugin  -i'
1491                else:
1492                    log.info(log.bold(
1493                        "Please install hp plugin's manually, otherwise some functionality may break"))
1494                if os_utils.execute(plugin_cmd) != 0:
1495                    log.error(
1496                        "hp-plugin command failed. Please run hp-plugin manually.")
1497            else:
1498                log.info(log.bold(
1499                    "Please install hp plugin's manually, otherwise some functionality may break"))
1500
1501        if core.selected_component == 'hplip':
1502            tui.title("RESTART OR RE-PLUG IS REQUIRED")
1503            cmd = "hp-setup"
1504            paragraph = """If you are installing a USB connected printer, and the printer was plugged in when you started this installer, you will need to either restart your PC or unplug and re-plug in your printer (USB cable only). If you choose to restart, run this command after restarting: %s  (Note: If you are using a parallel connection, you will have to restart your PC. If you are using network/wireless, you can ignore and continue).""" % cmd
1505
1506            for p in tui.format_paragraph(paragraph):
1507                log.info(p)
1508            log.info("")
1509
1510            ok, choice = tui.enter_choice("Restart or re-plug in your printer (r=restart, p=re-plug in*, i=ignore/continue, q=quit) : ",
1511                                          ['r', 'p', 'i'], 'p')
1512
1513            if not ok:
1514                tui.title("RE-STARTING HP_SYSTRAY")
1515                services.run_systray()
1516                sys.exit(0)
1517
1518            if choice == 'r':
1519                log.note("")
1520                log.note(
1521                    "IMPORTANT! Make sure to save all work in all open applications before restarting!")
1522
1523                ok, ans = tui.enter_yes_no(log.bold("Restart now"), 'n')
1524                if not ok:
1525                    tui.title("RE-STARTING HP_SYSTRAY")
1526                    services.run_systray()
1527                    sys.exit(0)
1528                if ans:
1529                    ok = services.restart(core.passwordObj)
1530                    if not ok:
1531                        log.error(
1532                            "Restart failed. Please restart using the system menu.")
1533
1534                tui.title("RE-STARTING HP_SYSTRAY")
1535                services.run_systray()
1536                sys.exit(0)
1537
1538            elif choice == 'p':  # 'p'
1539                if not tui.continue_prompt("Please unplug and re-plugin your printer now. "):
1540                    tui.title("RE-STARTING HP_SYSTRAY")
1541                    services.run_systray()
1542                    sys.exit(0)
1543
1544        #
1545        # SETUP PRINTER
1546        #
1547        if core.selected_component == 'hplip':
1548            tui.title("PRINTER SETUP")
1549
1550            if auto:
1551                install_printer = True
1552            else:
1553                ok, install_printer = tui.enter_yes_no(
1554                    "Would you like to setup a printer now")
1555                if not ok:
1556                    tui.title("RE-STARTING HP_SYSTRAY")
1557                    services.run_systray()
1558                    sys.exit(0)
1559
1560            if install_printer:
1561                log.info(
1562                    "Please make sure your printer is connected and powered on at this time.")
1563                ok, choice = tui.enter_choice(
1564                    "Do you want to setup printer in GUI mode? (u=GUI mode*, i=Interactive mode) : ", ['u', 'i'], 'u')
1565                if ok and choice == 'u':
1566                    setup_cmd = 'hp-setup  -u'
1567                    if os_utils.execute(setup_cmd) != 0:
1568                        log.error(
1569                            "hp-setup failed. Please run hp-setup manually.")
1570                    # if not services.run_hp_tools_with_auth('hp-setup', core.passwordObj):
1571                        #log.error("hp-setup failed. Please run hp-setup manually.")
1572
1573                elif ok and choice == 'i':
1574                    setup_cmd = 'hp-setup  -i'
1575                    log.info("Running '%s' command...." % setup_cmd)
1576                    if os_utils.execute(setup_cmd) != 0:
1577                        log.error(
1578                            "hp-setup failed. Please run hp-setup manually.")
1579
1580        tui.title("RE-STARTING HP_SYSTRAY")
1581        services.run_systray()
1582    except KeyboardInterrupt:
1583        log.info("")
1584        log.error("Aborted.")
1585
1586    sys.exit(0)
1587