Guest User

Untitled

a guest
Aug 5th, 2019
230
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 73.04 KB | None | 0 0
  1. #!/usr/bin/python3
  2. # -*- coding: utf-8; Mode: Python; indent-tabs-mode: nil; tab-width: 4 -*-
  3.  
  4. # Copyright (C) 2005 Javier Carranza and others for Guadalinex
  5. # Copyright (C) 2005, 2006, 2007, 2008, 2009 Canonical Ltd.
  6. # Copyright (C) 2007 Mario Limonciello
  7. #
  8. # This program is free software; you can redistribute it and/or modify
  9. # it under the terms of the GNU General Public License as published by
  10. # the Free Software Foundation; either version 2 of the License, or
  11. # (at your option) any later version.
  12. #
  13. # This program is distributed in the hope that it will be useful,
  14. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16. # GNU General Public License for more details.
  17. #
  18. # You should have received a copy of the GNU General Public License
  19. # along with this program; if not, write to the Free Software
  20. # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  21.  
  22. from __future__ import print_function
  23.  
  24. import fcntl
  25. import gzip
  26. import os
  27. import platform
  28. import pwd
  29. import re
  30. import shutil
  31. import socket
  32. import stat
  33. import struct
  34. import subprocess
  35. import sys
  36. import syslog
  37. import textwrap
  38. import traceback
  39.  
  40. import apt_pkg
  41. from apt.cache import Cache
  42. import debconf
  43.  
  44. sys.path.insert(0, '/usr/lib/ubiquity')
  45.  
  46. from ubiquity import install_misc, misc, osextras, plugin_manager
  47. from ubiquity.components import apt_setup, check_kernels, hw_detect
  48.  
  49.  
  50. INTERFACES_TEXT = """\
  51. # This file describes the network interfaces available on your system
  52. # and how to activate them. For more information, see interfaces(5).
  53.  
  54. # The loopback network interface
  55. auto lo
  56. iface lo inet loopback"""
  57.  
  58.  
  59. HOSTS_TEXT = """\
  60.  
  61. # The following lines are desirable for IPv6 capable hosts
  62. ::1     ip6-localhost ip6-loopback
  63. fe00::0 ip6-localnet
  64. ff00::0 ip6-mcastprefix
  65. ff02::1 ip6-allnodes
  66. ff02::2 ip6-allrouters"""
  67.  
  68.  
  69. IFTAB_TEXT = """\
  70. # This file assigns persistent names to network interfaces.
  71. # See iftab(5) for syntax.
  72. """
  73.  
  74.  
  75. def cleanup_after(func):
  76.     def wrapper(self):
  77.         try:
  78.             func(self)
  79.         finally:
  80.             self.cleanup()
  81.             try:
  82.                 self.db.progress('STOP')
  83.             except (KeyboardInterrupt, SystemExit):
  84.                 raise
  85.             except:
  86.                 pass
  87.     return wrapper
  88.  
  89.  
  90. class PluginProgress:
  91.     def __init__(self, db):
  92.         self._db = db
  93.  
  94.     def info(self, title):
  95.         self._db.progress('INFO', title)
  96.  
  97.     def get(self, question):
  98.         return self._db.get(question)
  99.  
  100.     def substitute(self, template, substr, data):
  101.         self._db.subst(template, substr, data)
  102.  
  103.  
  104. class Install(install_misc.InstallBase):
  105.     def __init__(self):
  106.         install_misc.InstallBase.__init__(self)
  107.  
  108.         self.db = debconf.Debconf()
  109.         self.kernel_version = platform.release()
  110.  
  111.         # Get langpacks from install
  112.         self.langpacks = []
  113.         if os.path.exists('/var/lib/ubiquity/langpacks'):
  114.             with open('/var/lib/ubiquity/langpacks') as langpacks:
  115.                 for line in langpacks:
  116.                     self.langpacks.append(line.strip())
  117.  
  118.         # Load plugins
  119.         modules = plugin_manager.load_plugins()
  120.         modules = plugin_manager.order_plugins(modules)
  121.         self.plugins = [x for x in modules if hasattr(x, 'Install')]
  122.  
  123.         if 'UBIQUITY_OEM_USER_CONFIG' in os.environ:
  124.             self.target = '/'
  125.             return
  126.  
  127.         apt_pkg.init_config()
  128.         apt_pkg.config.set("Dir", self.target)
  129.         apt_pkg.config.set("Dir::State::status",
  130.                            self.target_file('var/lib/dpkg/status'))
  131.         apt_pkg.config.set("APT::GPGV::TrustedKeyring",
  132.                            self.target_file('etc/apt/trusted.gpg'))
  133.  
  134.         # Keep this in sync with configure_apt.
  135.         # TODO cjwatson 2011-03-03: consolidate this.
  136.         try:
  137.             if self.db.get('base-installer/install-recommends') == 'false':
  138.                 apt_pkg.config.set("APT::Install-Recommends", "false")
  139.         except debconf.DebconfError:
  140.             pass
  141.         apt_pkg.config.set("APT::Authentication::TrustCDROM", "true")
  142.         apt_pkg.config.set("Acquire::gpgv::Options::",
  143.                            "--ignore-time-conflict")
  144.         try:
  145.             if self.db.get('debian-installer/allow_unauthenticated') == 'true':
  146.                 apt_pkg.config.set("APT::Get::AllowUnauthenticated", "true")
  147.                 apt_pkg.config.set(
  148.                     "Aptitude::CmdLine::Ignore-Trust-Violations", "true")
  149.         except debconf.DebconfError:
  150.             pass
  151.         apt_pkg.config.set("APT::CDROM::NoMount", "true")
  152.         apt_pkg.config.set("Acquire::cdrom::mount", "/cdrom")
  153.         apt_pkg.config.set("Acquire::cdrom::/cdrom/::Mount", "true")
  154.         apt_pkg.config.set("Acquire::cdrom::/cdrom/::UMount", "true")
  155.         apt_pkg.config.set("Acquire::cdrom::AutoDetect", "false")
  156.         apt_pkg.config.set("Dir::Media::MountPath", "/cdrom")
  157.  
  158.         apt_pkg.config.set("DPkg::Options::", "--root=%s" % self.target)
  159.         # We don't want apt-listchanges or dpkg-preconfigure, so just clear
  160.         # out the list of pre-installation hooks.
  161.         apt_pkg.config.clear("DPkg::Pre-Install-Pkgs")
  162.         apt_pkg.init_system()
  163.  
  164.         use_restricted = True
  165.         try:
  166.             if self.db.get('apt-setup/restricted') == 'false':
  167.                 use_restricted = False
  168.         except debconf.DebconfError:
  169.             pass
  170.         if not use_restricted:
  171.             self.restricted_cache = Cache()
  172.  
  173.     # TODO can we really pick up where install.py left off?  They're using two
  174.     # separate databases, which means two progress states.  Might need to
  175.     # record the progress position in find_next_step and pick up from there.
  176.     # Ask Colin.
  177.     @cleanup_after
  178.     def run(self):
  179.         """Main entry point."""
  180.         # We pick up where install.py left off.
  181.         if 'UBIQUITY_OEM_USER_CONFIG' in os.environ:
  182.             self.prev_count = 0
  183.         else:
  184.             self.prev_count = 74
  185.         self.count = self.prev_count
  186.         self.start = self.prev_count
  187.         self.end = self.start + 22 + len(self.plugins)
  188.  
  189.         self.db.progress(
  190.             'START', self.start, self.end, 'ubiquity/install/title')
  191.  
  192.         self.configure_python()
  193.  
  194.         self.next_region()
  195.         self.db.progress('INFO', 'ubiquity/install/network')
  196.         self.configure_network()
  197.  
  198.         self.configure_locale()
  199.  
  200.         self.next_region()
  201.         self.db.progress('INFO', 'ubiquity/install/apt')
  202.         self.configure_apt()
  203.  
  204.         self.configure_plugins()
  205.  
  206.         self.next_region()
  207.         self.run_target_config_hooks()
  208.  
  209.         self.next_region(size=5)
  210.         # Ignore failures from language pack installation.
  211.         try:
  212.             self.install_language_packs()
  213.         except install_misc.InstallStepError:
  214.             pass
  215.         except IOError:
  216.             pass
  217.         except SystemError:
  218.             pass
  219.  
  220.         self.next_region()
  221.         self.remove_unusable_kernels()
  222.  
  223.         self.next_region(size=4)
  224.         self.db.progress('INFO', 'ubiquity/install/hardware')
  225.         self.configure_hardware()
  226.  
  227.         # Tell apt-install to install packages directly from now on.
  228.         with open('/var/lib/ubiquity/apt-install-direct', 'w'):
  229.             pass
  230.  
  231.         self.next_region()
  232.         self.db.progress('INFO', 'ubiquity/install/installing')
  233.  
  234.         if 'UBIQUITY_OEM_USER_CONFIG' in os.environ:
  235.             self.install_oem_extras()
  236.         else:
  237.             self.install_extras()
  238.  
  239.         self.next_region()
  240.         self.db.progress('INFO', 'ubiquity/install/bootloader')
  241.         self.configure_bootloader()
  242.  
  243.         self.next_region(size=4)
  244.         self.db.progress('INFO', 'ubiquity/install/removing')
  245.         if 'UBIQUITY_OEM_USER_CONFIG' in os.environ:
  246.             try:
  247.                 if misc.create_bool(self.db.get('oem-config/remove_extras')):
  248.                     self.remove_oem_extras()
  249.             except debconf.DebconfError:
  250.                 pass
  251.         else:
  252.             self.remove_extras()
  253.  
  254.         self.next_region()
  255.         if 'UBIQUITY_OEM_USER_CONFIG' not in os.environ:
  256.             self.install_restricted_extras()
  257.  
  258.         self.db.progress('INFO', 'ubiquity/install/apt_clone_restore')
  259.         try:
  260.             self.apt_clone_restore()
  261.         except:
  262.             syslog.syslog(
  263.                 syslog.LOG_WARNING,
  264.                 'Could not restore packages from the previous install:')
  265.             for line in traceback.format_exc().split('\n'):
  266.                 syslog.syslog(syslog.LOG_WARNING, line)
  267.             self.db.input('critical', 'ubiquity/install/broken_apt_clone')
  268.             self.db.go()
  269.         try:
  270.             self.copy_network_config()
  271.         except:
  272.             syslog.syslog(
  273.                 syslog.LOG_WARNING,
  274.                 'Could not copy the network configuration:')
  275.             for line in traceback.format_exc().split('\n'):
  276.                 syslog.syslog(syslog.LOG_WARNING, line)
  277.             self.db.input('critical', 'ubiquity/install/broken_network_copy')
  278.             self.db.go()
  279.         try:
  280.             self.copy_bluetooth_config()
  281.         except:
  282.             syslog.syslog(
  283.                 syslog.LOG_WARNING,
  284.                 'Could not copy the bluetooth configuration:')
  285.             for line in traceback.format_exc().split('\n'):
  286.                 syslog.syslog(syslog.LOG_WARNING, line)
  287.             self.db.input('critical', 'ubiquity/install/broken_bluetooth_copy')
  288.             self.db.go()
  289.         try:
  290.             self.recache_apparmor()
  291.         except:
  292.             syslog.syslog(
  293.                 syslog.LOG_WARNING, 'Could not create an Apparmor cache:')
  294.             for line in traceback.format_exc().split('\n'):
  295.                 syslog.syslog(syslog.LOG_WARNING, line)
  296.         try:
  297.             self.copy_wallpaper_cache()
  298.         except:
  299.             syslog.syslog(
  300.                 syslog.LOG_WARNING, 'Could not copy wallpaper cache:')
  301.             for line in traceback.format_exc().split('\n'):
  302.                 syslog.syslog(syslog.LOG_WARNING, line)
  303.         self.copy_dcd()
  304.  
  305.         self.db.progress('SET', self.count)
  306.         self.db.progress('INFO', 'ubiquity/install/log_files')
  307.         self.copy_logs()
  308.         self.save_random_seed()
  309.  
  310.         self.db.progress('SET', self.end)
  311.  
  312.     def _get_uid_gid_on_target(self, target_user):
  313.         """Helper that gets the uid/gid of the username in the target chroot"""
  314.         uid = subprocess.Popen(
  315.             ['chroot', self.target, 'sudo', '-u', target_user, '--',
  316.              'id', '-u'], stdout=subprocess.PIPE, universal_newlines=True)
  317.         uid = uid.communicate()[0].strip('\n')
  318.         gid = subprocess.Popen(
  319.             ['chroot', self.target, 'sudo', '-u', target_user, '--',
  320.              'id', '-g'], stdout=subprocess.PIPE, universal_newlines=True)
  321.         gid = gid.communicate()[0].strip('\n')
  322.         try:
  323.             uid = int(uid)
  324.             gid = int(gid)
  325.         except ValueError:
  326.             return (None, None)
  327.         return uid, gid
  328.  
  329.     def configure_python(self):
  330.         """Byte-compile Python modules.
  331.  
  332.        To save space, Ubuntu excludes .pyc files from the live filesystem.
  333.        Recreate them now to restore the appearance of a system installed
  334.        from .debs.
  335.        """
  336.         cache = Cache()
  337.  
  338.         # Python standard library.
  339.         re_minimal = re.compile('^python\d+\.\d+-minimal$')
  340.         python_installed = sorted([
  341.             pkg[:-8] for pkg in cache.keys()
  342.             if re_minimal.match(pkg) and cache[pkg].is_installed])
  343.         for python in python_installed:
  344.             re_file = re.compile('^/usr/lib/%s/.*\.py$' % python)
  345.             files = [
  346.                 f for f in cache['%s-minimal' % python].installed_files
  347.                 if (re_file.match(f) and
  348.                     not os.path.exists(self.target_file('%sc' % f[1:])))]
  349.             install_misc.chrex(self.target, python,
  350.                                '/usr/lib/%s/py_compile.py' % python, *files)
  351.             files = [
  352.                 f for f in cache[python].installed_files
  353.                 if (re_file.match(f) and
  354.                     not os.path.exists(self.target_file('%sc' % f[1:])))]
  355.             install_misc.chrex(self.target, python,
  356.                                '/usr/lib/%s/py_compile.py' % python, *files)
  357.  
  358.         # Modules provided by the core Debian Python packages.
  359.         default = subprocess.Popen(
  360.             ['chroot', self.target, 'pyversions', '-d'],
  361.             stdout=subprocess.PIPE,
  362.             universal_newlines=True).communicate()[0].rstrip('\n')
  363.         if default:
  364.             install_misc.chrex(self.target, default, '-m', 'compileall',
  365.                                '/usr/share/python/')
  366.         if osextras.find_on_path_root(self.target, 'py3compile'):
  367.             install_misc.chrex(self.target, 'py3compile', '-p', 'python3',
  368.                                '/usr/share/python3/')
  369.  
  370.         def run_hooks(path, *args):
  371.             for hook in osextras.glob_root(self.target, path):
  372.                 if not os.access(self.target_file(hook[1:]), os.X_OK):
  373.                     continue
  374.                 install_misc.chrex(self.target, hook, *args)
  375.  
  376.         # Public and private modules provided by other packages.
  377.         install_misc.chroot_setup(self.target)
  378.         try:
  379.             if osextras.find_on_path_root(self.target, 'pyversions'):
  380.                 supported = subprocess.Popen(
  381.                     ['chroot', self.target, 'pyversions', '-s'],
  382.                     stdout=subprocess.PIPE,
  383.                     universal_newlines=True).communicate()[0].rstrip('\n')
  384.                 for python in supported.split():
  385.                     try:
  386.                         cachedpython = cache['%s-minimal' % python]
  387.                     except KeyError:
  388.                         continue
  389.                     if not cachedpython.is_installed:
  390.                         continue
  391.                     version = cachedpython.installed.version
  392.                     run_hooks('/usr/share/python/runtime.d/*.rtinstall',
  393.                               'rtinstall', python, '', version)
  394.                     run_hooks('/usr/share/python/runtime.d/*.rtupdate',
  395.                               'pre-rtupdate', python, python)
  396.                     run_hooks('/usr/share/python/runtime.d/*.rtupdate',
  397.                               'rtupdate', python, python)
  398.                     run_hooks('/usr/share/python/runtime.d/*.rtupdate',
  399.                               'post-rtupdate', python, python)
  400.  
  401.             if osextras.find_on_path_root(self.target, 'py3versions'):
  402.                 supported = subprocess.Popen(
  403.                     ['chroot', self.target, 'py3versions', '-s'],
  404.                     stdout=subprocess.PIPE,
  405.                     universal_newlines=True).communicate()[0].rstrip('\n')
  406.                 for python in supported.split():
  407.                     try:
  408.                         cachedpython = cache['%s-minimal' % python]
  409.                     except KeyError:
  410.                         continue
  411.                     if not cachedpython.is_installed:
  412.                         continue
  413.                     version = cachedpython.installed.version
  414.                     run_hooks('/usr/share/python3/runtime.d/*.rtinstall',
  415.                               'rtinstall', python, '', version)
  416.                     run_hooks('/usr/share/python3/runtime.d/*.rtupdate',
  417.                               'pre-rtupdate', python, python)
  418.                     run_hooks('/usr/share/python3/runtime.d/*.rtupdate',
  419.                               'rtupdate', python, python)
  420.                     run_hooks('/usr/share/python3/runtime.d/*.rtupdate',
  421.                               'post-rtupdate', python, python)
  422.         finally:
  423.             install_misc.chroot_cleanup(self.target)
  424.  
  425.     def configure_network(self):
  426.         """Automatically configure the network.
  427.  
  428.        At present, the only thing the user gets to tweak in the UI is the
  429.        hostname. Some other things will be copied from the live filesystem,
  430.        so changes made there will be reflected in the installed system.
  431.  
  432.        Unfortunately, at present we have to duplicate a fair bit of netcfg
  433.        here, because it's hard to drive netcfg in a way that won't try to
  434.        bring interfaces up and down.
  435.        """
  436.         # TODO cjwatson 2006-03-30: just call netcfg instead of doing all
  437.         # this; requires a netcfg binary that doesn't bring interfaces up
  438.         # and down
  439.  
  440.         if self.target != '/':
  441.             for path in ('/etc/network/interfaces', '/etc/resolv.conf'):
  442.                 if os.path.exists(path):
  443.                     targetpath = self.target_file(path[1:])
  444.                     st = os.lstat(path)
  445.                     if stat.S_ISLNK(st.st_mode):
  446.                         if os.path.lexists(targetpath):
  447.                             os.unlink(targetpath)
  448.                         linkto = os.readlink(path)
  449.                         os.symlink(linkto, targetpath)
  450.                     else:
  451.                         shutil.copy2(path, targetpath)
  452.         else:
  453.             if not os.path.exists('/etc/network/interfaces'):
  454.                 # Make sure there's at least something here so that ifupdown
  455.                 # doesn't get upset at boot.
  456.                 with open('/etc/network/interfaces', 'w') as interfaces:
  457.                     print(INTERFACES_TEXT, file=interfaces)
  458.  
  459.         try:
  460.             hostname = self.db.get('netcfg/get_hostname')
  461.         except debconf.DebconfError:
  462.             hostname = ''
  463.         try:
  464.             domain = self.db.get('netcfg/get_domain').rstrip('.')
  465.         except debconf.DebconfError:
  466.             domain = ''
  467.         if hostname == '':
  468.             hostname = 'ubuntu'
  469.  
  470.         with open(self.target_file('etc/hosts'), 'w') as hosts:
  471.             print("127.0.0.1\tlocalhost", file=hosts)
  472.             if domain:
  473.                 print("127.0.1.1\t%s.%s\t%s" % (hostname, domain, hostname),
  474.                       file=hosts)
  475.             else:
  476.                 print("127.0.1.1\t%s" % hostname, file=hosts)
  477.             print(HOSTS_TEXT, file=hosts)
  478.  
  479.         # Network Manager's ifupdown plugin has an inotify watch on
  480.         # /etc/hostname, which can trigger a race condition if /etc/hostname is
  481.         # written and immediately followed with /etc/hosts.
  482.         with open(self.target_file('etc/hostname'), 'w') as fp:
  483.             print(hostname, file=fp)
  484.  
  485.         if 'UBIQUITY_OEM_USER_CONFIG' in os.environ:
  486.             os.system("hostname %s" % hostname)
  487.  
  488.         persistent_net = '/etc/udev/rules.d/70-persistent-net.rules'
  489.         if os.path.exists(persistent_net):
  490.             if self.target != '/':
  491.                 shutil.copy2(
  492.                     persistent_net, self.target_file(persistent_net[1:]))
  493.         else:
  494.             # TODO cjwatson 2006-03-30: from <bits/ioctls.h>; ugh, but no
  495.             # binding available
  496.             SIOCGIFHWADDR = 0x8927
  497.             # <net/if_arp.h>
  498.             ARPHRD_ETHER = 1
  499.  
  500.             if_names = {}
  501.             sock = socket.socket(socket.SOCK_DGRAM)
  502.             interfaces = install_misc.get_all_interfaces()
  503.             for i in range(len(interfaces)):
  504.                 if_names[interfaces[i]] = struct.unpack(
  505.                     'H6s', fcntl.ioctl(
  506.                         sock.fileno(), SIOCGIFHWADDR,
  507.                         struct.pack('256s', interfaces[i].encode()))[16:24])
  508.             sock.close()
  509.  
  510.             with open(self.target_file('etc/iftab'), 'w') as iftab:
  511.                 print(IFTAB_TEXT, file=iftab)
  512.  
  513.                 for i in range(len(interfaces)):
  514.                     dup = False
  515.  
  516.                     if_name = if_names[interfaces[i]]
  517.                     if if_name is None or if_name[0] != ARPHRD_ETHER:
  518.                         continue
  519.  
  520.                     for j in range(len(interfaces)):
  521.                         if i == j or if_names[interfaces[j]] is None:
  522.                             continue
  523.                         if if_name[1] != if_names[interfaces[j]][1]:
  524.                             continue
  525.  
  526.                         if if_names[interfaces[j]][0] == ARPHRD_ETHER:
  527.                             dup = True
  528.  
  529.                     if dup:
  530.                         continue
  531.  
  532.                     line = (interfaces[i] + " mac " +
  533.                             ':'.join(['%02x' % if_name[1][c]
  534.                                       for c in range(6)]))
  535.                     line += " arp %d" % if_name[0]
  536.                     print(line, file=iftab)
  537.  
  538.     def run_plugin(self, plugin):
  539.         """Run a single install plugin."""
  540.         self.next_region()
  541.         # set a generic info message in case plugin doesn't provide one
  542.         self.db.progress('INFO', 'ubiquity/install/title')
  543.         inst = plugin.Install(None, db=self.db)
  544.         ret = inst.install(self.target, PluginProgress(self.db))
  545.         if ret:
  546.             raise install_misc.InstallStepError(
  547.                 "Plugin %s failed with code %s" % (plugin.NAME, ret))
  548.  
  549.     def configure_locale(self):
  550.         """Configure the locale by running the language plugin.
  551.  
  552.        We need to do this as early as possible so that apt can emit
  553.        properly-localised messages when running in the target system.
  554.        """
  555.         try:
  556.             language_plugin = [
  557.                 plugin for plugin in self.plugins
  558.                 if (plugin_manager.get_mod_string(plugin, "NAME") ==
  559.                     "language")][0]
  560.         except IndexError:
  561.             return
  562.         self.run_plugin(language_plugin)
  563.         # Don't run this plugin again.
  564.         self.plugins = [
  565.             plugin for plugin in self.plugins if plugin != language_plugin]
  566.  
  567.     def configure_plugins(self):
  568.         """Apply plugin settings to installed system."""
  569.         for plugin in self.plugins:
  570.             self.run_plugin(plugin)
  571.  
  572.     def configure_apt(self):
  573.         """Configure /etc/apt/sources.list."""
  574.         if 'UBIQUITY_OEM_USER_CONFIG' in os.environ:
  575.             return  # apt will already be setup as the OEM wants
  576.  
  577.         # TODO cjwatson 2007-07-06: Much of the following is
  578.         # cloned-and-hacked from base-installer/debian/postinst. Perhaps we
  579.         # should come up with a way to avoid this.
  580.  
  581.         # Keep this in sync with __init__.
  582.  
  583.         try:
  584.             if self.db.get('base-installer/install-recommends') == 'false':
  585.                 tf = self.target_file('etc/apt/apt.conf.d/00InstallRecommends')
  586.                 with open(tf, 'w') as apt_conf_ir:
  587.                     print('APT::Install-Recommends "false";', file=apt_conf_ir)
  588.         except debconf.DebconfError:
  589.             pass
  590.  
  591.         # Make apt trust CDs. This is not on by default (we think).
  592.         # This will be left in place on the installed system.
  593.         tf = self.target_file('etc/apt/apt.conf.d/00trustcdrom')
  594.         with open(tf, 'w') as apt_conf_tc:
  595.             print('APT::Authentication::TrustCDROM "true";', file=apt_conf_tc)
  596.  
  597.         # Avoid clock skew causing gpg verification issues.
  598.         # This file will be left in place until the end of the install.
  599.         tf = self.target_file('etc/apt/apt.conf.d/00IgnoreTimeConflict')
  600.         with open(tf, 'w') as apt_conf_itc:
  601.             print('Acquire::gpgv::Options { "--ignore-time-conflict"; };',
  602.                   file=apt_conf_itc)
  603.  
  604.         try:
  605.             if self.db.get('debian-installer/allow_unauthenticated') == 'true':
  606.                 tf = self.target_file(
  607.                     'etc/apt/apt.conf.d/00AllowUnauthenticated')
  608.                 with open(tf, 'w') as apt_conf_au:
  609.                     print('APT::Get::AllowUnauthenticated "true";',
  610.                           file=apt_conf_au)
  611.                     print('Aptitude::CmdLine::Ignore-Trust-Violations "true";',
  612.                           file=apt_conf_au)
  613.         except debconf.DebconfError:
  614.             pass
  615.  
  616.         # let apt inside the chroot see the cdrom
  617.         if self.target != "/":
  618.             target_cdrom = self.target_file('cdrom')
  619.             misc.execute('umount', target_cdrom)
  620.             if not os.path.exists(target_cdrom):
  621.                 if os.path.lexists(target_cdrom):
  622.                     os.unlink(target_cdrom)
  623.                 os.mkdir(target_cdrom)
  624.             misc.execute('mount', '--bind', '/cdrom', target_cdrom)
  625.  
  626.         # Make apt-cdrom and apt not unmount/mount CD-ROMs.
  627.         # This file will be left in place until the end of the install.
  628.         tf = self.target_file('etc/apt/apt.conf.d/00NoMountCDROM')
  629.         with open(tf, 'w') as apt_conf_nmc:
  630.             print(textwrap.dedent("""\
  631.                APT::CDROM::NoMount "true";
  632.                Acquire::cdrom {
  633.                  mount "/cdrom";
  634.                  "/cdrom/" {
  635.                    Mount  "true";
  636.                    UMount "true";
  637.                  };
  638.                  AutoDetect "false";
  639.                };
  640.                Dir::Media::MountPath "/cdrom";"""), file=apt_conf_nmc)
  641.  
  642.         # This will be reindexed after installation based on the full
  643.         # installed sources.list.
  644.         try:
  645.             shutil.rmtree(
  646.                 self.target_file('var/lib/apt-xapian-index'),
  647.                 ignore_errors=True)
  648.         except OSError:
  649.             pass
  650.  
  651.         dbfilter = apt_setup.AptSetup(None, self.db)
  652.         ret = dbfilter.run_command(auto_process=True)
  653.         if ret != 0:
  654.             raise install_misc.InstallStepError(
  655.                 "AptSetup failed with code %d" % ret)
  656.  
  657.     def run_target_config_hooks(self):
  658.         """Run hook scripts from /usr/lib/ubiquity/target-config.
  659.  
  660.        This allows casper to hook into us and repeat bits of its
  661.        configuration in the target system.
  662.        """
  663.         if 'UBIQUITY_OEM_USER_CONFIG' in os.environ:
  664.             return  # These were already run once during install
  665.  
  666.         hookdir = '/usr/lib/ubiquity/target-config'
  667.  
  668.         if os.path.isdir(hookdir):
  669.             # Exclude hooks containing '.', so that *.dpkg-* et al are avoided.
  670.             hooks = [entry for entry in os.listdir(hookdir)
  671.                      if '.' not in entry]
  672.             self.db.progress('START', 0, len(hooks), 'ubiquity/install/title')
  673.             self.db.progress('INFO', 'ubiquity/install/target_hooks')
  674.             for hookentry in hooks:
  675.                 hook = os.path.join(hookdir, hookentry)
  676.                 syslog.syslog('running %s' % hook)
  677.                 if not os.access(hook, os.X_OK):
  678.                     self.db.progress('STEP', 1)
  679.                     continue
  680.                 # Errors are ignored at present, although this may change.
  681.                 subprocess.call(['log-output', '-t', 'ubiquity',
  682.                                  '--pass-stdout', hook])
  683.                 self.db.progress('STEP', 1)
  684.             self.db.progress('STOP')
  685.  
  686.     def install_language_packs(self):
  687.         if not self.langpacks:
  688.             return
  689.  
  690.         self.do_install(self.langpacks, langpacks=True)
  691.         self.verify_language_packs()
  692.  
  693.     def verify_language_packs(self):
  694.         if os.path.exists('/var/lib/ubiquity/no-install-langpacks'):
  695.             return  # always complete enough
  696.  
  697.         if self.db.get('pkgsel/ignore-incomplete-language-support') == 'true':
  698.             return
  699.  
  700.         cache = Cache()
  701.         incomplete = False
  702.         for pkg in self.langpacks:
  703.             if pkg.startswith('gimp-help-'):
  704.                 # gimp-help-common is far too big to fit on CDs, so don't
  705.                 # worry about it.
  706.                 continue
  707.             cachedpkg = install_misc.get_cache_pkg(cache, pkg)
  708.             if cachedpkg is None or not cachedpkg.is_installed:
  709.                 syslog.syslog('incomplete language support: %s missing' % pkg)
  710.                 incomplete = True
  711.                 break
  712.         if incomplete:
  713.             language_support_dir = \
  714.                 self.target_file('usr/share/language-support')
  715.             update_notifier_dir = \
  716.                 self.target_file('var/lib/update-notifier/user.d')
  717.             for note in ('incomplete-language-support-gnome.note',
  718.                          'incomplete-language-support-qt.note'):
  719.                 notepath = os.path.join(language_support_dir, note)
  720.                 if os.path.exists(notepath):
  721.                     if not os.path.exists(update_notifier_dir):
  722.                         os.makedirs(update_notifier_dir)
  723.                     shutil.copy(notepath,
  724.                                 os.path.join(update_notifier_dir, note))
  725.                     break
  726.  
  727.     def traverse_for_kernel(self, cache, pkg):
  728.         kern = install_misc.get_cache_pkg(cache, pkg)
  729.         if kern is None:
  730.             return None
  731.         pkc = cache._depcache.get_candidate_ver(kern._pkg)
  732.         if 'Depends' in pkc.depends_list:
  733.             dependencies = pkc.depends_list['Depends']
  734.         else:
  735.             # Didn't find.
  736.             return None
  737.         for dep in dependencies:
  738.             name = dep[0].target_pkg.name
  739.             if name.startswith('linux-image-2.'):
  740.                 return name
  741.             elif name.startswith('linux-'):
  742.                 return self.traverse_for_kernel(cache, name)
  743.  
  744.     def remove_unusable_kernels(self):
  745.         """Remove unusable kernels.
  746.  
  747.        Keeping these may cause us to be unable to boot.
  748.        """
  749.         if 'UBIQUITY_OEM_USER_CONFIG' in os.environ:
  750.             return
  751.  
  752.         self.db.progress('START', 0, 5, 'ubiquity/install/title')
  753.  
  754.         self.db.progress('INFO', 'ubiquity/install/find_removables')
  755.  
  756.         # Check for kernel packages to remove.
  757.         dbfilter = check_kernels.CheckKernels(None, self.db)
  758.         dbfilter.run_command(auto_process=True)
  759.  
  760.         install_kernels = set()
  761.         new_kernel_pkg = None
  762.         new_kernel_version = None
  763.         install_kernels_path = "/var/lib/ubiquity/install-kernels"
  764.         if os.path.exists(install_kernels_path):
  765.             with open(install_kernels_path) as install_kernels_file:
  766.                 for line in install_kernels_file:
  767.                     kernel = line.strip()
  768.                     install_kernels.add(kernel)
  769.                     # If we decided to actively install a particular kernel
  770.                     # like this, it's probably because we prefer it to the
  771.                     # default one, so we'd better update kernel_version to
  772.                     # match.
  773.                     if kernel.startswith('linux-image-2.'):
  774.                         new_kernel_pkg = kernel
  775.                         new_kernel_version = kernel[12:]
  776.                     elif kernel.startswith('linux-generic-'):
  777.                         # Traverse dependencies to find the real kernel image.
  778.                         cache = Cache()
  779.                         kernel = self.traverse_for_kernel(cache, kernel)
  780.                         if kernel:
  781.                             new_kernel_pkg = kernel
  782.                             new_kernel_version = kernel[12:]
  783.             install_kernels_file.close()
  784.  
  785.         remove_kernels = set()
  786.         remove_kernels_path = "/var/lib/ubiquity/remove-kernels"
  787.         if os.path.exists(remove_kernels_path):
  788.             with open(remove_kernels_path) as remove_kernels_file:
  789.                 for line in remove_kernels_file:
  790.                     remove_kernels.add(line.strip())
  791.  
  792.         if len(install_kernels) == 0 and len(remove_kernels) == 0:
  793.             self.db.progress('STOP')
  794.             return
  795.  
  796.         # TODO cjwatson 2009-10-19: These regions are rather crude and
  797.         # should be improved.
  798.         self.db.progress('SET', 1)
  799.         self.progress_region(1, 2)
  800.         if install_kernels:
  801.             self.do_install(install_kernels)
  802.             install_misc.record_installed(install_kernels)
  803.             if new_kernel_pkg:
  804.                 cache = Cache()
  805.                 cached_pkg = install_misc.get_cache_pkg(cache, new_kernel_pkg)
  806.                 if cached_pkg is not None and cached_pkg.is_installed:
  807.                     self.kernel_version = new_kernel_version
  808.                 else:
  809.                     remove_kernels = []
  810.                 del cache
  811.             else:
  812.                 remove_kernels = []
  813.  
  814.         self.db.progress('SET', 2)
  815.         self.progress_region(2, 5)
  816.         try:
  817.             if remove_kernels:
  818.                 install_misc.record_removed(remove_kernels, recursive=True)
  819.         except:
  820.             self.db.progress('STOP')
  821.             raise
  822.         self.db.progress('SET', 5)
  823.         self.db.progress('STOP')
  824.  
  825.     def get_resume_partition(self):
  826.         biggest_size = 0
  827.         biggest_partition = None
  828.         try:
  829.             with open('/proc/swaps') as swaps:
  830.                 for line in swaps:
  831.                     words = line.split()
  832.                     if words[1] != 'partition':
  833.                         continue
  834.                     if not os.path.exists(words[0]):
  835.                         continue
  836.                     if words[0].startswith('/dev/ramzswap'):
  837.                         continue
  838.                     size = int(words[2])
  839.                     if size > biggest_size:
  840.                         biggest_size = size
  841.                         biggest_partition = words[0]
  842.         except Exception:
  843.             return None
  844.         return biggest_partition
  845.  
  846.     def configure_hardware(self):
  847.         """Reconfigure several hardware-specific packages.
  848.  
  849.        These packages depend on the hardware of the system where the live
  850.        filesystem was built, and must be reconfigured to work properly on
  851.        the installed system.
  852.        """
  853.         self.nested_progress_start()
  854.         install_misc.chroot_setup(self.target)
  855.         try:
  856.             dbfilter = hw_detect.HwDetect(None, self.db)
  857.             ret = dbfilter.run_command(auto_process=True)
  858.             if ret != 0:
  859.                 raise install_misc.InstallStepError(
  860.                     "HwDetect failed with code %d" % ret)
  861.         finally:
  862.             install_misc.chroot_cleanup(self.target)
  863.         self.nested_progress_end()
  864.  
  865.         self.db.progress('INFO', 'ubiquity/install/hardware')
  866.  
  867.         script = '/usr/lib/ubiquity/debian-installer-utils' \
  868.                  '/register-module.post-base-installer'
  869.         if 'UBIQUITY_OEM_USER_CONFIG' in os.environ:
  870.             script += '-oem'
  871.         misc.execute(script)
  872.  
  873.         resume = self.get_resume_partition()
  874.         if resume is not None:
  875.             resume_uuid = None
  876.             try:
  877.                 resume_uuid = subprocess.Popen(
  878.                     ['block-attr', '--uuid', resume],
  879.                     stdout=subprocess.PIPE,
  880.                     universal_newlines=True).communicate()[0].rstrip('\n')
  881.             except OSError:
  882.                 pass
  883.             if resume_uuid:
  884.                 resume = "UUID=%s" % resume_uuid
  885.             if os.path.exists(self.target_file('etc/initramfs-tools/conf.d')):
  886.                 configdir = self.target_file('etc/initramfs-tools/conf.d')
  887.             elif os.path.exists(self.target_file('etc/mkinitramfs/conf.d')):
  888.                 configdir = self.target_file('etc/mkinitramfs/conf.d')
  889.             else:
  890.                 configdir = None
  891.             if configdir is not None:
  892.                 resume_path = os.path.join(configdir, 'resume')
  893.                 with open(resume_path, 'w') as configfile:
  894.                     print("RESUME=%s" % resume, file=configfile)
  895.  
  896.         osextras.unlink_force(self.target_file('etc/popularity-contest.conf'))
  897.         try:
  898.             participate = self.db.get('popularity-contest/participate')
  899.             install_misc.set_debconf(
  900.                 self.target, 'popularity-contest/participate', participate,
  901.                 self.db)
  902.         except debconf.DebconfError:
  903.             pass
  904.  
  905.         osextras.unlink_force(self.target_file('etc/papersize'))
  906.         subprocess.call(['log-output', '-t', 'ubiquity', 'chroot', self.target,
  907.                          'ucf', '--purge', '/etc/papersize'],
  908.                         preexec_fn=install_misc.debconf_disconnect,
  909.                         close_fds=True)
  910.         try:
  911.             install_misc.set_debconf(
  912.                 self.target, 'libpaper/defaultpaper', '', self.db)
  913.         except debconf.DebconfError:
  914.             pass
  915.  
  916.         osextras.unlink_force(
  917.             self.target_file('etc/ssl/certs/ssl-cert-snakeoil.pem'))
  918.         osextras.unlink_force(
  919.             self.target_file('etc/ssl/private/ssl-cert-snakeoil.key'))
  920.  
  921.         # ensure /etc/mtab is a symlink
  922.         osextras.unlink_force(self.target_file('etc/mtab'))
  923.         os.symlink('../proc/self/mounts', self.target_file('etc/mtab'))
  924.  
  925.         install_misc.chroot_setup(self.target, x11=True)
  926.         install_misc.chrex(
  927.             self.target, 'dpkg-divert', '--package', 'ubiquity', '--rename',
  928.             '--quiet', '--add', '/usr/sbin/update-initramfs')
  929.         try:
  930.             os.symlink(
  931.                 '/bin/true', self.target_file('usr/sbin/update-initramfs'))
  932.         except OSError:
  933.             pass
  934.  
  935.         packages = ['linux-image-' + self.kernel_version,
  936.                     'popularity-contest',
  937.                     'libpaper1',
  938.                     'ssl-cert']
  939.         arch, subarch = install_misc.archdetect()
  940.  
  941.         # this postinst installs EFI application and cleans old entries
  942.         if arch in ('amd64', 'i386') and subarch == 'efi':
  943.             packages.append('fwupdate')
  944.  
  945.         try:
  946.             for package in packages:
  947.                 install_misc.reconfigure(self.target, package)
  948.         finally:
  949.             osextras.unlink_force(
  950.                 self.target_file('usr/sbin/update-initramfs'))
  951.             install_misc.chrex(
  952.                 self.target, 'dpkg-divert', '--package', 'ubiquity',
  953.                 '--rename', '--quiet', '--remove',
  954.                 '/usr/sbin/update-initramfs')
  955.             install_misc.chrex(
  956.                 self.target, 'update-initramfs', '-c',
  957.                 '-k', self.kernel_version)
  958.             install_misc.chroot_cleanup(self.target, x11=True)
  959.  
  960.         # Fix up kernel symlinks now that the initrd exists. Depending on
  961.         # the architecture, these may be in / or in /boot.
  962.         bootdir = self.target_file('boot')
  963.         if self.db.get('base-installer/kernel/linux/link_in_boot') == 'true':
  964.             linkdir = bootdir
  965.             linkprefix = ''
  966.         else:
  967.             linkdir = self.target
  968.             linkprefix = 'boot'
  969.  
  970.         # Remove old symlinks. We'll set them up from scratch.
  971.         re_symlink = re.compile('vmlinu[xz]|initrd.img$')
  972.         for entry in os.listdir(linkdir):
  973.             if re_symlink.match(entry) is not None:
  974.                 filename = os.path.join(linkdir, entry)
  975.                 if os.path.islink(filename):
  976.                     os.unlink(filename)
  977.         if linkdir != self.target:
  978.             # Remove symlinks in /target too, which may have been created on
  979.             # the live filesystem. This isn't necessary, but it may help
  980.             # avoid confusion.
  981.             for entry in os.listdir(self.target):
  982.                 if re_symlink.match(entry) is not None:
  983.                     filename = self.target_file(entry)
  984.                     if os.path.islink(filename):
  985.                         os.unlink(filename)
  986.  
  987.         # Create symlinks. Prefer our current kernel version if possible,
  988.         # but if not (perhaps due to a customised live filesystem image),
  989.         # it's better to create some symlinks than none at all.
  990.         re_image = re.compile('(vmlinu[xz]|initrd.img)-')
  991.         for entry in os.listdir(bootdir):
  992.             match = re_image.match(entry)
  993.             if match is not None:
  994.                 imagetype = match.group(1)
  995.                 linksrc = os.path.join(linkprefix, entry)
  996.                 linkdst = os.path.join(linkdir, imagetype)
  997.                 if os.path.exists(linkdst):
  998.                     if entry.endswith('-' + self.kernel_version):
  999.                         os.unlink(linkdst)
  1000.                     else:
  1001.                         continue
  1002.                 os.symlink(linksrc, linkdst)
  1003.  
  1004.     def configure_bootloader(self):
  1005.         """Configure and install the boot loader."""
  1006.         if 'UBIQUITY_OEM_USER_CONFIG' in os.environ:
  1007.             # the language might be different than initial install.
  1008.             # recopy translations if we have them now
  1009.             full_lang = self.db.get('debian-installer/locale').split('.')[0]
  1010.             for lang in [full_lang.split('.')[0], full_lang.split('_')[0]]:
  1011.                 source = (
  1012.                     '/usr/share/locale-langpack/%s/LC_MESSAGES/grub.mo' % lang)
  1013.                 if (os.path.exists(source) and
  1014.                         os.path.isdir('/boot/grub/locale')):
  1015.                     shutil.copy(source, '/boot/grub/locale/%s.mo' % lang)
  1016.                     break
  1017.             return
  1018.  
  1019.         inst_boot = self.db.get('ubiquity/install_bootloader')
  1020.         if inst_boot == 'true' and 'UBIQUITY_NO_BOOTLOADER' not in os.environ:
  1021.             binds = ("/proc", "/sys", "/dev", "/run")
  1022.             for bind in binds:
  1023.                 misc.execute('mount', '--bind', bind, self.target + bind)
  1024.  
  1025.             arch, subarch = install_misc.archdetect()
  1026.  
  1027.             try:
  1028.                 if arch in ('amd64', 'i386'):
  1029.                     from ubiquity.components import grubinstaller
  1030.                     while 1:
  1031.                         dbfilter = grubinstaller.GrubInstaller(None, self.db)
  1032.                         ret = dbfilter.run_command(auto_process=True)
  1033.                         if subarch == 'efi' and ret != 0:
  1034.                             raise install_misc.InstallStepError(
  1035.                                 "GrubInstaller failed with code %d" % ret)
  1036.                         elif ret != 0:
  1037.                             old_bootdev = self.db.get('grub-installer/bootdev')
  1038.                             bootdev = 'ubiquity/install/new-bootdev'
  1039.                             self.db.fset(bootdev, 'seen', 'false')
  1040.                             self.db.set(bootdev, old_bootdev)
  1041.                             self.db.input('critical', bootdev)
  1042.                             self.db.go()
  1043.                             response = self.db.get(bootdev)
  1044.                             if response == 'skip':
  1045.                                 break
  1046.                             if not response:
  1047.                                 raise install_misc.InstallStepError(
  1048.                                     "GrubInstaller failed with code %d" % ret)
  1049.                             else:
  1050.                                 self.db.set('grub-installer/bootdev', response)
  1051.                         else:
  1052.                             break
  1053.                 elif (arch in ('armel', 'armhf') and
  1054.                       subarch in ('omap', 'omap4', 'mx5')):
  1055.                     from ubiquity.components import flash_kernel
  1056.                     dbfilter = flash_kernel.FlashKernel(None, self.db)
  1057.                     ret = dbfilter.run_command(auto_process=True)
  1058.                     if ret != 0:
  1059.                         raise install_misc.InstallStepError(
  1060.                             "FlashKernel failed with code %d" % ret)
  1061.                 elif arch == 'powerpc':
  1062.                     from ubiquity.components import yabootinstaller
  1063.                     dbfilter = yabootinstaller.YabootInstaller(None, self.db)
  1064.                     ret = dbfilter.run_command(auto_process=True)
  1065.                     if ret != 0:
  1066.                         raise install_misc.InstallStepError(
  1067.                             "YabootInstaller failed with code %d" % ret)
  1068.                 else:
  1069.                     raise install_misc.InstallStepError(
  1070.                         "No bootloader installer found")
  1071.             except ImportError:
  1072.                 raise install_misc.InstallStepError(
  1073.                     "No bootloader installer found")
  1074.  
  1075.             for bind in binds:
  1076.                 misc.execute('umount', '-f', self.target + bind)
  1077.  
  1078.     def do_remove(self, to_remove, recursive=False):
  1079.         self.nested_progress_start()
  1080.  
  1081.         self.db.progress('START', 0, 5, 'ubiquity/install/title')
  1082.         self.db.progress('INFO', 'ubiquity/install/find_removables')
  1083.  
  1084.         fetchprogress = install_misc.DebconfAcquireProgress(
  1085.             self.db, 'ubiquity/install/title',
  1086.             'ubiquity/install/apt_indices_starting',
  1087.             'ubiquity/install/apt_indices')
  1088.         cache = Cache()
  1089.  
  1090.         if cache._depcache.broken_count > 0:
  1091.             syslog.syslog(
  1092.                 'not processing removals, since there are broken packages: '
  1093.                 '%s' % ', '.join(install_misc.broken_packages(cache)))
  1094.             self.db.progress('STOP')
  1095.             self.nested_progress_end()
  1096.             return
  1097.  
  1098.         with cache.actiongroup():
  1099.             install_misc.get_remove_list(cache, to_remove, recursive)
  1100.  
  1101.         self.db.progress('SET', 1)
  1102.         self.progress_region(1, 5)
  1103.         fetchprogress = install_misc.DebconfAcquireProgress(
  1104.             self.db, 'ubiquity/install/title', None,
  1105.             'ubiquity/install/fetch_remove')
  1106.         installprogress = install_misc.DebconfInstallProgress(
  1107.             self.db, 'ubiquity/install/title', 'ubiquity/install/apt_info',
  1108.             'ubiquity/install/apt_error_remove')
  1109.         install_misc.chroot_setup(self.target)
  1110.         commit_error = None
  1111.         try:
  1112.             try:
  1113.                 if not cache.commit(fetchprogress, installprogress):
  1114.                     fetchprogress.stop()
  1115.                     installprogress.finish_update()
  1116.                     self.db.progress('STOP')
  1117.                     self.nested_progress_end()
  1118.                     return
  1119.             except SystemError as e:
  1120.                 for line in traceback.format_exc().split('\n'):
  1121.                     syslog.syslog(syslog.LOG_ERR, line)
  1122.                 commit_error = str(e)
  1123.         finally:
  1124.             install_misc.chroot_cleanup(self.target)
  1125.         self.db.progress('SET', 5)
  1126.  
  1127.         cache.open(None)
  1128.         if commit_error or cache._depcache.broken_count > 0:
  1129.             if commit_error is None:
  1130.                 commit_error = ''
  1131.             brokenpkgs = install_misc.broken_packages(cache)
  1132.             syslog.syslog('broken packages after removal: '
  1133.                           '%s' % ', '.join(brokenpkgs))
  1134.             self.db.subst('ubiquity/install/broken_remove', 'ERROR',
  1135.                           commit_error)
  1136.             self.db.subst('ubiquity/install/broken_remove', 'PACKAGES',
  1137.                           ', '.join(brokenpkgs))
  1138.             self.db.input('critical', 'ubiquity/install/broken_remove')
  1139.             self.db.go()
  1140.  
  1141.         self.db.progress('STOP')
  1142.  
  1143.         self.nested_progress_end()
  1144.  
  1145.     def install_oem_extras(self):
  1146.         """Try to install additional packages requested by the distributor."""
  1147.         try:
  1148.             inst_langpacks = \
  1149.                 self.db.get('oem-config/install-language-support') == 'true'
  1150.         except debconf.DebconfError:
  1151.             inst_langpacks = False
  1152.         if inst_langpacks:
  1153.             self.select_language_packs()
  1154.             recorded = install_misc.query_recorded_installed()
  1155.  
  1156.         try:
  1157.             extra_packages = self.db.get('oem-config/extra_packages')
  1158.             if extra_packages:
  1159.                 extra_packages = extra_packages.replace(',', ' ').split()
  1160.             elif not inst_langpacks:
  1161.                 return
  1162.             else:
  1163.                 extra_packages = []
  1164.         except debconf.DebconfError:
  1165.             if not inst_langpacks:
  1166.                 return
  1167.  
  1168.         if inst_langpacks:
  1169.             extra_packages += recorded
  1170.  
  1171.         save_replace = None
  1172.         save_override = None
  1173.         custom = '/etc/apt/sources.list.d/oem-config.list'
  1174.         apt_update = ['debconf-apt-progress', '--', 'apt-get', 'update']
  1175.         trusted_db = '/etc/apt/trusted.gpg'
  1176.         try:
  1177.             if 'DEBCONF_DB_REPLACE' in os.environ:
  1178.                 save_replace = os.environ['DEBCONF_DB_REPLACE']
  1179.             if 'DEBCONF_DB_OVERRIDE' in os.environ:
  1180.                 save_override = os.environ['DEBCONF_DB_OVERRIDE']
  1181.             os.environ['DEBCONF_DB_REPLACE'] = 'configdb'
  1182.             os.environ['DEBCONF_DB_OVERRIDE'] = 'Pipe{infd:none outfd:none}'
  1183.  
  1184.             try:
  1185.                 extra_pool = self.db.get('oem-config/repository')
  1186.             except debconf.DebconfError:
  1187.                 extra_pool = ''
  1188.             try:
  1189.                 extra_key = self.db.get('oem-config/key')
  1190.             except debconf.DebconfError:
  1191.                 extra_key = ''
  1192.  
  1193.             if extra_pool:
  1194.                 with open(custom, 'w') as f:
  1195.                     print(extra_pool, file=f)
  1196.             if extra_key and os.path.exists(extra_key):
  1197.                 if os.path.exists(trusted_db):
  1198.                     shutil.copy(trusted_db, trusted_db + '.oem-config')
  1199.                 subprocess.call(['apt-key', 'add', extra_key])
  1200.             if extra_pool:
  1201.                 subprocess.call(apt_update)
  1202.             # We don't support asking questions on behalf of packages specified
  1203.             # here yet, as we don't support asking arbitrary questions in
  1204.             # components/install.py yet.  This is complicated not only by the
  1205.             # present lack of dialogs for string and multiselect, but also
  1206.             # because we don't have any way of discerning between questions
  1207.             # asked by this module and questions asked by packages being
  1208.             # installed.
  1209.             cmd = ['debconf-apt-progress', '--', 'apt-get', '-y', 'install']
  1210.             cmd += extra_packages
  1211.             try:
  1212.                 subprocess.check_call(cmd)
  1213.             except subprocess.CalledProcessError as e:
  1214.                 if e.returncode != 30:
  1215.                     cache = Cache()
  1216.                     brokenpkgs = install_misc.broken_packages(cache)
  1217.                     self.warn_broken_packages(brokenpkgs, str(e))
  1218.         finally:
  1219.             if os.path.exists(trusted_db + '.oem-config'):
  1220.                 shutil.copy(trusted_db + '.oem-config', trusted_db)
  1221.             if os.path.exists(custom):
  1222.                 os.unlink(custom)
  1223.                 subprocess.call(apt_update)
  1224.             if save_replace:
  1225.                 os.environ['DEBCONF_DB_REPLACE'] = save_replace
  1226.             if save_override:
  1227.                 os.environ['DEBCONF_DB_OVERRIDE'] = save_override
  1228.  
  1229.         if inst_langpacks:
  1230.             self.verify_language_packs()
  1231.  
  1232.     def install_restricted_extras(self):
  1233.         if self.db.get('ubiquity/use_nonfree') == 'true':
  1234.             self.db.progress('INFO', 'ubiquity/install/nonfree')
  1235.             packages = self.db.get('ubiquity/nonfree_package').split()
  1236.             self.do_install(packages)
  1237.  
  1238.     def install_extras(self):
  1239.         """Try to install packages requested by installer components."""
  1240.         # We only ever install these packages from the CD.
  1241.         sources_list = self.target_file('etc/apt/sources.list')
  1242.         os.rename(sources_list, "%s.apt-setup" % sources_list)
  1243.         with open("%s.apt-setup" % sources_list) as old_sources:
  1244.             with open(sources_list, 'w') as new_sources:
  1245.                 found_cdrom = False
  1246.                 for line in old_sources:
  1247.                     if 'cdrom:' in line:
  1248.                         print(line, end="", file=new_sources)
  1249.                         found_cdrom = True
  1250.         if not found_cdrom:
  1251.             os.rename("%s.apt-setup" % sources_list, sources_list)
  1252.  
  1253.         self.do_install(install_misc.query_recorded_installed())
  1254.  
  1255.         if found_cdrom:
  1256.             os.rename("%s.apt-setup" % sources_list, sources_list)
  1257.  
  1258.         # TODO cjwatson 2007-08-09: python reimplementation of
  1259.         # oem-config/finish-install.d/07oem-config-user. This really needs
  1260.         # to die in a great big chemical fire and call the same shell script
  1261.         # instead.
  1262.         try:
  1263.             if self.db.get('oem-config/enable') == 'true':
  1264.                 if os.path.isdir(self.target_file('home/oem')):
  1265.                     with open(self.target_file('home/oem/.hwdb'), 'w'):
  1266.                         pass
  1267.  
  1268.                     apps_dir = 'usr/share/applications'
  1269.                     for desktop_file in (
  1270.                             apps_dir + '/oem-config-prepare-gtk.desktop',
  1271.                             apps_dir + '/kde4/oem-config-prepare-kde.desktop'):
  1272.                         if os.path.exists(self.target_file(desktop_file)):
  1273.                             desktop_base = os.path.basename(desktop_file)
  1274.                             install_misc.chrex(
  1275.                                 self.target, 'install', '-d',
  1276.                                 '-o', 'oem', '-g', 'oem',
  1277.                                 '/home/oem/Desktop')
  1278.                             install_misc.chrex(
  1279.                                 self.target, 'install',
  1280.                                 '-o', 'oem', '-g', 'oem',
  1281.                                 '/%s' % desktop_file,
  1282.                                 '/home/oem/Desktop/%s' % desktop_base)
  1283.                             break
  1284.  
  1285.                 # Carry the locale setting over to the installed system.
  1286.                 # This mimics the behavior in 01oem-config-udeb.
  1287.                 di_locale = self.db.get('debian-installer/locale')
  1288.                 if di_locale:
  1289.                     install_misc.set_debconf(
  1290.                         self.target, 'debian-installer/locale', di_locale,
  1291.                         self.db)
  1292.                 # in an automated install, this key needs to carry over
  1293.                 installable_lang = self.db.get(
  1294.                     'ubiquity/only-show-installable-languages')
  1295.                 if installable_lang:
  1296.                     install_misc.set_debconf(
  1297.                         self.target,
  1298.                         'ubiquity/only-show-installable-languages',
  1299.                         installable_lang, self.db)
  1300.         except debconf.DebconfError:
  1301.             pass
  1302.  
  1303.     def remove_oem_extras(self):
  1304.         """Remove unnecessary packages in OEM mode.
  1305.  
  1306.        Try to remove packages that were not part of the base install and
  1307.        are not needed by the final system.
  1308.  
  1309.        This is roughly the set of packages installed by ubiquity + packages
  1310.        we explicitly installed in oem-config (langpacks, for example) -
  1311.        everything else.
  1312.        """
  1313.         manifest = '/var/lib/ubiquity/installed-packages'
  1314.         if not os.path.exists(manifest):
  1315.             return
  1316.  
  1317.         keep = set()
  1318.         with open(manifest) as manifest_file:
  1319.             for line in manifest_file:
  1320.                 if line.strip() != '' and not line.startswith('#'):
  1321.                     keep.add(line.split()[0])
  1322.         # Let's not rip out the ground beneath our feet.
  1323.         keep.add('ubiquity')
  1324.         keep.add('oem-config')
  1325.  
  1326.         cache = Cache()
  1327.         # TODO cjwatson 2012-05-04: It would be nice to use a set
  1328.         # comprehension here, but that causes:
  1329.         #   SyntaxError: can not delete variable 'cache' referenced in nested
  1330.         #   scope
  1331.         remove = set([pkg for pkg in cache.keys() if cache[pkg].is_installed])
  1332.         # Keep packages we explicitly installed.
  1333.         keep |= install_misc.query_recorded_installed()
  1334.         remove -= install_misc.expand_dependencies_simple(cache, keep, remove)
  1335.         del cache
  1336.  
  1337.         install_misc.record_removed(remove)
  1338.         (regular, recursive) = install_misc.query_recorded_removed()
  1339.         self.do_remove(regular)
  1340.         self.do_remove(recursive, recursive=True)
  1341.  
  1342.     def copy_tree(self, source, target, uid, gid):
  1343.         # Mostly stolen from copy_all.
  1344.         directory_times = []
  1345.         s = '/'
  1346.         for p in target.split(os.sep)[1:]:
  1347.             s = os.path.join(s, p)
  1348.             if not os.path.exists(s):
  1349.                 os.mkdir(s)
  1350.                 os.lchown(s, uid, gid)
  1351.         for dirpath, dirnames, filenames in os.walk(source):
  1352.             sp = dirpath[len(source) + 1:]
  1353.             for name in dirnames + filenames:
  1354.                 relpath = os.path.join(sp, name)
  1355.                 sourcepath = os.path.join(source, relpath)
  1356.                 targetpath = os.path.join(target, relpath)
  1357.                 st = os.lstat(sourcepath)
  1358.  
  1359.                 # Remove the target if necessary and if we can.
  1360.                 install_misc.remove_target(source, target, relpath, st)
  1361.  
  1362.                 # Now actually copy source to target.
  1363.                 mode = stat.S_IMODE(st.st_mode)
  1364.                 if stat.S_ISLNK(st.st_mode):
  1365.                     linkto = os.readlink(sourcepath)
  1366.                     os.symlink(linkto, targetpath)
  1367.                 elif stat.S_ISDIR(st.st_mode):
  1368.                     if not os.path.isdir(targetpath):
  1369.                         os.mkdir(targetpath, mode)
  1370.                 elif stat.S_ISCHR(st.st_mode):
  1371.                     os.mknod(targetpath, stat.S_IFCHR | mode, st.st_rdev)
  1372.                 elif stat.S_ISBLK(st.st_mode):
  1373.                     os.mknod(targetpath, stat.S_IFBLK | mode, st.st_rdev)
  1374.                 elif stat.S_ISFIFO(st.st_mode):
  1375.                     os.mknod(targetpath, stat.S_IFIFO | mode)
  1376.                 elif stat.S_ISSOCK(st.st_mode):
  1377.                     os.mknod(targetpath, stat.S_IFSOCK | mode)
  1378.                 elif stat.S_ISREG(st.st_mode):
  1379.                     install_misc.copy_file(
  1380.                         self.db, sourcepath, targetpath, True)
  1381.  
  1382.                 os.lchown(targetpath, uid, gid)
  1383.                 if not stat.S_ISLNK(st.st_mode):
  1384.                     os.chmod(targetpath, mode)
  1385.                 if stat.S_ISDIR(st.st_mode):
  1386.                     directory_times.append(
  1387.                         (targetpath, st.st_atime, st.st_mtime))
  1388.                 # os.utime() sets timestamp of target, not link
  1389.                 elif not stat.S_ISLNK(st.st_mode):
  1390.                     try:
  1391.                         os.utime(targetpath, (st.st_atime, st.st_mtime))
  1392.                     except Exception:
  1393.                         # We can live with timestamps being wrong.
  1394.                         pass
  1395.  
  1396.         # Apply timestamps to all directories now that the items within them
  1397.         # have been copied.
  1398.         for dirtime in directory_times:
  1399.             (directory, atime, mtime) = dirtime
  1400.             try:
  1401.                 os.utime(directory, (atime, mtime))
  1402.             except Exception:
  1403.                 # I have no idea why I've been getting lots of bug reports
  1404.                 # about this failing, but I really don't care. Ignore it.
  1405.                 pass
  1406.  
  1407.     def remove_extras(self):
  1408.         """Remove unnecessary packages.
  1409.  
  1410.        Try to remove packages that are needed on the live CD but not on the
  1411.        installed system.
  1412.        """
  1413.         # Looking through files for packages to remove is pretty quick, so
  1414.         # don't bother with a progress bar for that.
  1415.  
  1416.         # Check for packages specific to the live CD.  (manifest-desktop is
  1417.         # the old method, which listed all the packages to keep;
  1418.         # manifest-remove is the new method, which lists all the packages to
  1419.         # remove.)
  1420.         manifest_remove = os.path.join(self.casper_path,
  1421.                                        'filesystem.manifest-remove')
  1422.         manifest_desktop = os.path.join(self.casper_path,
  1423.                                         'filesystem.manifest-desktop')
  1424.         manifest = os.path.join(self.casper_path, 'filesystem.manifest')
  1425.         if os.path.exists(manifest_remove) and os.path.exists(manifest):
  1426.             difference = set()
  1427.             with open(manifest_remove) as manifest_file:
  1428.                 for line in manifest_file:
  1429.                     if line.strip() != '' and not line.startswith('#'):
  1430.                         pkg = line.split(':')[0]
  1431.                         difference.add(pkg.split()[0])
  1432.             live_packages = set()
  1433.             with open(manifest) as manifest_file:
  1434.                 for line in manifest_file:
  1435.                     if line.strip() != '' and not line.startswith('#'):
  1436.                         pkg = line.split(':')[0]
  1437.                         live_packages.add(pkg.split()[0])
  1438.             desktop_packages = live_packages - difference
  1439.         elif os.path.exists(manifest_desktop) and os.path.exists(manifest):
  1440.             desktop_packages = set()
  1441.             with open(manifest_desktop) as manifest_file:
  1442.                 for line in manifest_file:
  1443.                     if line.strip() != '' and not line.startswith('#'):
  1444.                         pkg = line.split(':')[0]
  1445.                         desktop_packages.add(pkg.split()[0])
  1446.             live_packages = set()
  1447.             with open(manifest) as manifest_file:
  1448.                 for line in manifest_file:
  1449.                     if line.strip() != '' and not line.startswith('#'):
  1450.                         pkg = line.split(':')[0]
  1451.                         live_packages.add(pkg.split()[0])
  1452.             difference = live_packages - desktop_packages
  1453.         else:
  1454.             difference = set()
  1455.  
  1456.         # Keep packages we explicitly installed.
  1457.         keep = install_misc.query_recorded_installed()
  1458.  
  1459.         arch, subarch = install_misc.archdetect()
  1460.  
  1461.         if arch in ('amd64', 'i386'):
  1462.             for pkg in ('grub', 'grub-pc', 'grub-efi', 'grub-efi-amd64',
  1463.                         'grub-efi-amd64-signed', 'shim-signed', 'mokutil',
  1464.                         'lilo'):
  1465.                 if pkg not in keep:
  1466.                     difference.add(pkg)
  1467.  
  1468.         cache = Cache()
  1469.         difference -= install_misc.expand_dependencies_simple(
  1470.             cache, keep, difference)
  1471.         del cache
  1472.  
  1473.         if len(difference) == 0:
  1474.             return
  1475.  
  1476.         use_restricted = True
  1477.         try:
  1478.             if self.db.get('apt-setup/restricted') == 'false':
  1479.                 use_restricted = False
  1480.         except debconf.DebconfError:
  1481.             pass
  1482.         if not use_restricted:
  1483.             cache = self.restricted_cache
  1484.             for pkg in cache.keys():
  1485.                 if (cache[pkg].is_installed and
  1486.                         cache[pkg].section.startswith('restricted/')):
  1487.                     difference.add(pkg)
  1488.             del cache
  1489.  
  1490.         install_misc.record_removed(difference)
  1491.  
  1492.         # Don't worry about failures removing packages; it will be easier
  1493.         # for the user to sort them out with a graphical package manager (or
  1494.         # whatever) after installation than it will be to try to deal with
  1495.         # them automatically here.
  1496.         (regular, recursive) = install_misc.query_recorded_removed()
  1497.         self.do_remove(regular)
  1498.         self.do_remove(recursive, recursive=True)
  1499.  
  1500.         oem_remove_extras = False
  1501.         try:
  1502.             oem_remove_extras = misc.create_bool(
  1503.                 self.db.get('oem-config/remove_extras'))
  1504.         except debconf.DebconfError:
  1505.             pass
  1506.  
  1507.         if oem_remove_extras:
  1508.             installed = (desktop_packages | keep - regular - recursive)
  1509.             if not os.path.exists(self.target_file('var/lib/ubiquity')):
  1510.                 os.makedirs(self.target_file('var/lib/ubiquity'))
  1511.             p = self.target_file('var/lib/ubiquity/installed-packages')
  1512.             with open(p, 'w') as fp:
  1513.                 for line in installed:
  1514.                     print(line, file=fp)
  1515.  
  1516.     def apt_clone_restore(self):
  1517.         if 'UBIQUITY_OEM_USER_CONFIG' in os.environ:
  1518.             return
  1519.         import lsb_release
  1520.         working = self.target_file('ubiquity-apt-clone')
  1521.         working = os.path.join(working,
  1522.                                'apt-clone-state-%s.tar.gz' % os.uname()[1])
  1523.         codename = lsb_release.get_distro_information()['CODENAME']
  1524.         if not os.path.exists(working):
  1525.             return
  1526.         install_misc.chroot_setup(self.target)
  1527.         binds = ("/proc", "/sys", "/dev", "/run")
  1528.         try:
  1529.             for bind in binds:
  1530.                 misc.execute('mount', '--bind', bind, self.target + bind)
  1531.             restore_cmd = [
  1532.                 'apt-clone', 'restore-new-distro',
  1533.                 working, codename, '--destination', self.target]
  1534.             subprocess.check_call(
  1535.                 restore_cmd, preexec_fn=install_misc.debconf_disconnect)
  1536.         finally:
  1537.             install_misc.chroot_cleanup(self.target)
  1538.             for bind in binds:
  1539.                 misc.execute('umount', '-f', self.target + bind)
  1540.  
  1541.     def copy_network_config(self):
  1542.         if 'UBIQUITY_OEM_USER_CONFIG' in os.environ:
  1543.             return
  1544.         try:
  1545.             if self.db.get('oem-config/enable') == 'true':
  1546.                 return
  1547.         except debconf.DebconfError:
  1548.             pass
  1549.  
  1550.         source_nm = "/etc/NetworkManager/system-connections/"
  1551.         target_nm = "/target/etc/NetworkManager/system-connections/"
  1552.  
  1553.         # Sanity checks.  We don't want to do anything if a network
  1554.         # configuration already exists on the target
  1555.         if os.path.exists(source_nm) and os.path.exists(target_nm):
  1556.             for network in os.listdir(source_nm):
  1557.                 # Skip LTSP live
  1558.                 if network == "LTSP":
  1559.                     continue
  1560.  
  1561.                 source_network = os.path.join(source_nm, network)
  1562.                 target_network = os.path.join(target_nm, network)
  1563.  
  1564.                 if os.path.exists(target_network):
  1565.                     continue
  1566.  
  1567.                 shutil.copy(source_network, target_network)
  1568.  
  1569.     def copy_bluetooth_config(self):
  1570.         if 'UBIQUITY_OEM_USER_CONFIG' in os.environ:
  1571.             return
  1572.         try:
  1573.             if self.db.get('oem-config/enable') == 'true':
  1574.                 return
  1575.         except debconf.DebconfError:
  1576.             pass
  1577.  
  1578.         source_bluetooth = "/var/lib/bluetooth/"
  1579.         target_bluetooth = "/target/var/lib/bluetooth/"
  1580.  
  1581.         # Ensure the target doesn't exist
  1582.         if os.path.exists(target_bluetooth):
  1583.             shutil.rmtree(target_bluetooth)
  1584.  
  1585.         # Copy /var/lib/bluetooth to /target/var/lib/bluetooth/
  1586.         if os.path.exists(source_bluetooth):
  1587.             shutil.copytree(source_bluetooth, target_bluetooth)
  1588.  
  1589.     def recache_apparmor(self):
  1590.         """Generate an apparmor cache to speed up boot time."""
  1591.         if 'UBIQUITY_OEM_USER_CONFIG' in os.environ:
  1592.             return
  1593.         if not os.path.exists(self.target_file('etc/init.d/apparmor')):
  1594.             syslog.syslog(
  1595.                 'Apparmor is not installed, so not generating cache.')
  1596.             return
  1597.         install_misc.chrex(self.target, 'mount', '-t', 'proc', 'proc', '/proc')
  1598.         install_misc.chrex(
  1599.             self.target, 'mount', '-t', 'sysfs', 'sysfs', '/sys')
  1600.         install_misc.chrex(
  1601.             self.target, 'mount', '-t', 'securityfs',
  1602.             'securityfs', '/sys/kernel/security')
  1603.         install_misc.chrex(self.target, '/etc/init.d/apparmor', 'recache')
  1604.         install_misc.chrex(self.target, 'umount', '/proc')
  1605.         install_misc.chrex(self.target, 'umount', '/sys/kernel/security')
  1606.         install_misc.chrex(self.target, 'umount', '/sys')
  1607.  
  1608.     def copy_wallpaper_cache(self):
  1609.         """Copy GNOME wallpaper cache for the benefit of ureadahead.
  1610.  
  1611.        Only do this on systems with gnome-settings-daemon.
  1612.        """
  1613.         if 'UBIQUITY_OEM_USER_CONFIG' in os.environ:
  1614.             return
  1615.  
  1616.         # We don't use the copy_network_config casper user trick as it's not
  1617.         # ubuntu in install mode.
  1618.         try:
  1619.             casper_user = pwd.getpwuid(999).pw_name
  1620.         except KeyError:
  1621.             # We're on a weird system where the casper user isn't uid 999
  1622.             # just stop there
  1623.             return
  1624.  
  1625.         casper_user_home = os.path.expanduser('~%s' % casper_user)
  1626.         casper_user_wallpaper_cache_dir = os.path.join(casper_user_home,
  1627.                                                        '.cache', 'wallpaper')
  1628.         target_user = self.db.get('passwd/username')
  1629.         target_user_cache_dir = self.target_file('home', target_user, '.cache')
  1630.         target_user_wallpaper_cache_dir = os.path.join(target_user_cache_dir,
  1631.                                                        'wallpaper')
  1632.         if (not os.path.isdir(target_user_wallpaper_cache_dir) and
  1633.                 os.path.isdir(casper_user_wallpaper_cache_dir)):
  1634.  
  1635.             # copy to targeted user
  1636.             uid = subprocess.Popen(
  1637.                 ['chroot', self.target, 'sudo', '-u', target_user, '--',
  1638.                  'id', '-u'],
  1639.                 stdout=subprocess.PIPE,
  1640.                 universal_newlines=True).communicate()[0].strip('\n')
  1641.             gid = subprocess.Popen(
  1642.                 ['chroot', self.target, 'sudo', '-u', target_user, '--',
  1643.                  'id', '-g'],
  1644.                 stdout=subprocess.PIPE,
  1645.                 universal_newlines=True).communicate()[0].strip('\n')
  1646.             uid = int(uid)
  1647.             gid = int(gid)
  1648.             self.copy_tree(casper_user_wallpaper_cache_dir,
  1649.                            target_user_wallpaper_cache_dir, uid, gid)
  1650.             os.chmod(target_user_cache_dir, 0o700)
  1651.             os.chmod(target_user_wallpaper_cache_dir, 0o700)
  1652.  
  1653.     def copy_dcd(self):
  1654.         """Install the Distribution Channel Descriptor (DCD) file."""
  1655.         dcd = '/cdrom/.disk/ubuntu_dist_channel'
  1656.         if os.path.exists(dcd):
  1657.             shutil.copy(dcd, self.target_file('var/lib/ubuntu_dist_channel'))
  1658.  
  1659.     def copy_logs(self):
  1660.         """Copy log files to the installed system."""
  1661.         if 'UBIQUITY_OEM_USER_CONFIG' in os.environ:
  1662.             return
  1663.  
  1664.         target_dir = self.target_file('var/log/installer')
  1665.         if not os.path.exists(target_dir):
  1666.             os.makedirs(target_dir)
  1667.  
  1668.         for log_file in ('/var/log/syslog', '/var/log/partman',
  1669.                          '/var/log/installer/version', '/var/log/casper.log',
  1670.                          '/var/log/installer/debug'):
  1671.             target_log_file = os.path.join(target_dir,
  1672.                                            os.path.basename(log_file))
  1673.             if os.path.isfile(log_file):
  1674.                 if not misc.execute('cp', '-a', log_file, target_log_file):
  1675.                     syslog.syslog(syslog.LOG_ERR,
  1676.                                   'Failed to copy installation log file')
  1677.                 os.chmod(target_log_file, stat.S_IRUSR | stat.S_IWUSR)
  1678.         media_info = '/cdrom/.disk/info'
  1679.         if os.path.isfile(media_info):
  1680.             try:
  1681.                 target_media_info = \
  1682.                     self.target_file('var/log/installer/media-info')
  1683.                 shutil.copy(media_info, target_media_info)
  1684.                 os.chmod(target_media_info,
  1685.                          stat.S_IRUSR | stat.S_IWUSR |
  1686.                          stat.S_IRGRP | stat.S_IROTH)
  1687.             except (IOError, OSError):
  1688.                 pass
  1689.  
  1690.         try:
  1691.             status = open(self.target_file('var/lib/dpkg/status'), 'rb')
  1692.             status_gz = gzip.open(os.path.join(target_dir,
  1693.                                                'initial-status.gz'), 'w')
  1694.             while True:
  1695.                 data = status.read(65536)
  1696.                 if not data:
  1697.                     break
  1698.                 status_gz.write(data)
  1699.             status_gz.close()
  1700.             status.close()
  1701.         except IOError:
  1702.             pass
  1703.         try:
  1704.             if self.db.get('oem-config/enable') == 'true':
  1705.                 oem_id = self.db.get('oem-config/id')
  1706.                 tf = self.target_file('var/log/installer/oem-id')
  1707.                 with open(tf, 'w') as oem_id_file:
  1708.                     print(oem_id, file=oem_id_file)
  1709.         except (debconf.DebconfError, IOError):
  1710.             pass
  1711.         try:
  1712.             path = self.target_file('ubiquity-apt-clone')
  1713.             if os.path.exists(path):
  1714.                 shutil.move(path, self.target_file('var/log/installer'))
  1715.         except IOError:
  1716.             pass
  1717.  
  1718.     def save_random_seed(self):
  1719.         """Save random seed to the target system.
  1720.  
  1721.        This arranges for the installed system to have better entropy on
  1722.        first boot.
  1723.        """
  1724.         if 'UBIQUITY_OEM_USER_CONFIG' in os.environ:
  1725.             return
  1726.  
  1727.         try:
  1728.             st = os.stat("/dev/urandom")
  1729.         except OSError:
  1730.             return
  1731.         if not stat.S_ISCHR(st.st_mode):
  1732.             return
  1733.         if not os.path.isdir(self.target_file("var/lib/systemd")):
  1734.             return
  1735.  
  1736.         poolbytes = 512
  1737.         try:
  1738.             with open("/proc/sys/kernel/random/poolsize") as poolsize:
  1739.                 poolbits = int(poolsize.readline())
  1740.                 if poolbits:
  1741.                     poolbytes = int((poolbits + 7) / 8)
  1742.         except IOError:
  1743.             pass
  1744.  
  1745.         old_umask = os.umask(0o077)
  1746.         try:
  1747.             with open("/dev/urandom", "rb") as urandom:
  1748.                 with open(self.target_file("var/lib/systemd/random-seed"),
  1749.                           "wb") as seed:
  1750.                     seed.write(urandom.read(poolbytes))
  1751.         except IOError:
  1752.             pass
  1753.         finally:
  1754.             os.umask(old_umask)
  1755.  
  1756.     def cleanup(self):
  1757.         """Miscellaneous cleanup tasks."""
  1758.         misc.execute('umount', self.target_file('cdrom'))
  1759.  
  1760.         env = dict(os.environ)
  1761.         env['OVERRIDE_BASE_INSTALLABLE'] = '1'
  1762.         subprocess.call(['/usr/lib/ubiquity/apt-setup/finish-install'],
  1763.                         env=env)
  1764.  
  1765.         for apt_conf in ('00NoMountCDROM', '00IgnoreTimeConflict',
  1766.                          '00AllowUnauthenticated'):
  1767.             osextras.unlink_force(
  1768.                 self.target_file('etc/apt/apt.conf.d', apt_conf))
  1769.  
  1770.  
  1771. if __name__ == '__main__':
  1772.     os.environ['DPKG_UNTRANSLATED_MESSAGES'] = '1'
  1773.     if not os.path.exists('/var/lib/ubiquity'):
  1774.         os.makedirs('/var/lib/ubiquity')
  1775.  
  1776.     install = Install()
  1777.     sys.excepthook = install_misc.excepthook
  1778.     install.run()
  1779.     sys.exit(0)
  1780.  
  1781. # vim:ai:et:sts=4:tw=80:sw=4:
Advertisement
Add Comment
Please, Sign In to add comment