home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2007 September / PCWSEP07.iso / Software / Linux / Linux Mint 3.0 Light / LinuxMint-3.0-Light.iso / casper / filesystem.squashfs / usr / share / ubiquity / install.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2007-04-29  |  43.7 KB  |  1,512 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.5)
  3.  
  4. import sys
  5. import os
  6. import platform
  7. import errno
  8. import stat
  9. import re
  10. import textwrap
  11. import shutil
  12. import subprocess
  13. import time
  14. import struct
  15. import socket
  16. import fcntl
  17. import traceback
  18. import syslog
  19. import gzip
  20. import debconf
  21. import apt_pkg
  22. from apt.cache import Cache
  23. from apt.progress import FetchProgress, InstallProgress
  24. sys.path.insert(0, '/usr/lib/ubiquity')
  25. from ubiquity import misc
  26. from ubiquity.components import language_apply, apt_setup, timezone_apply, clock_setup, console_setup_apply, usersetup_apply, hw_detect, check_kernels, migrationassistant_apply
  27.  
  28. class DebconfFetchProgress(FetchProgress):
  29.     """An object that reports apt's fetching progress using debconf."""
  30.     
  31.     def __init__(self, db, title, info_starting, info):
  32.         FetchProgress.__init__(self)
  33.         self.db = db
  34.         self.title = title
  35.         self.info_starting = info_starting
  36.         self.info = info
  37.         self.old_capb = None
  38.         self.eta = 0
  39.  
  40.     
  41.     def start(self):
  42.         self.db.progress('START', 0, 100, self.title)
  43.         if self.info_starting is not None:
  44.             self.db.progress('INFO', self.info_starting)
  45.         
  46.         self.old_capb = self.db.capb()
  47.         capb_list = self.old_capb.split()
  48.         capb_list.append('progresscancel')
  49.         self.db.capb(' '.join(capb_list))
  50.  
  51.     
  52.     def pulse(self):
  53.         FetchProgress.pulse(self)
  54.         
  55.         try:
  56.             self.db.progress('SET', int(self.percent))
  57.         except debconf.DebconfError:
  58.             return False
  59.  
  60.         if self.eta != 0:
  61.             time_str = '%d:%02d' % divmod(int(self.eta), 60)
  62.             self.db.subst(self.info, 'TIME', time_str)
  63.             
  64.             try:
  65.                 self.db.progress('INFO', self.info)
  66.             except debconf.DebconfError:
  67.                 return False
  68.             except:
  69.                 None<EXCEPTION MATCH>debconf.DebconfError
  70.             
  71.  
  72.         None<EXCEPTION MATCH>debconf.DebconfError
  73.         return True
  74.  
  75.     
  76.     def stop(self):
  77.         if self.old_capb is not None:
  78.             self.db.capb(self.old_capb)
  79.             self.old_capb = None
  80.             self.db.progress('STOP')
  81.         
  82.  
  83.  
  84.  
  85. class DebconfInstallProgress(InstallProgress):
  86.     """An object that reports apt's installation progress using debconf."""
  87.     
  88.     def __init__(self, db, title, info, error = None):
  89.         InstallProgress.__init__(self)
  90.         self.db = db
  91.         self.title = title
  92.         self.info = info
  93.         self.error_template = error
  94.         self.started = False
  95.         flags = fcntl.fcntl(self.statusfd.fileno(), fcntl.F_GETFL)
  96.         fcntl.fcntl(self.statusfd.fileno(), fcntl.F_SETFL, flags & ~(os.O_NONBLOCK))
  97.  
  98.     
  99.     def startUpdate(self):
  100.         self.db.progress('START', 0, 100, self.title)
  101.         self.started = True
  102.  
  103.     
  104.     def error(self, pkg, errormsg):
  105.         if self.error_template is not None:
  106.             self.db.subst(self.error_template, 'PACKAGE', pkg)
  107.             self.db.subst(self.error_template, 'MESSAGE', errormsg)
  108.             self.db.input('critical', self.error_template)
  109.             self.db.go()
  110.         
  111.  
  112.     
  113.     def statusChange(self, pkg, percent, status):
  114.         self.percent = percent
  115.         self.status = status
  116.         self.db.progress('SET', int(percent))
  117.         self.db.subst(self.info, 'DESCRIPTION', status)
  118.         self.db.progress('INFO', self.info)
  119.  
  120.     
  121.     def updateInterface(self):
  122.         if self.statusfd is None:
  123.             return False
  124.         
  125.         
  126.         try:
  127.             while not self.read.endswith('\n'):
  128.                 r = os.read(self.statusfd.fileno(), 1)
  129.                 if not r:
  130.                     return False
  131.                 
  132.                 self.read += r
  133.                 continue
  134.                 self
  135.         except OSError:
  136.             (err, errstr) = None
  137.             print errstr
  138.  
  139.         if self.read.endswith('\n'):
  140.             s = self.read
  141.             (status, pkg, percent, status_str) = s.split(':', 3)
  142.             if status == 'pmerror':
  143.                 self.error(pkg, status_str)
  144.             elif status == 'pmconffile':
  145.                 match = re.compile("\\s*'(.*)'\\s*'(.*)'.*").match(status_str)
  146.                 if match:
  147.                     self.conffile(match.group(1), match.group(2))
  148.                 
  149.             else:
  150.                 self.statusChange(pkg, float(percent), status_str.strip())
  151.             self.read = ''
  152.         
  153.         return True
  154.  
  155.     
  156.     def run(self, pm):
  157.         child_pid = self.fork()
  158.         if child_pid == 0:
  159.             os.close(self.writefd)
  160.             
  161.             try:
  162.                 while self.updateInterface():
  163.                     pass
  164.             except (KeyboardInterrupt, SystemExit):
  165.                 pass
  166.             except:
  167.                 for line in traceback.format_exc().split('\n'):
  168.                     syslog.syslog(syslog.LOG_WARNING, line)
  169.                 
  170.  
  171.             os._exit(0)
  172.         
  173.         self.statusfd.close()
  174.         saved_stdout = os.dup(1)
  175.         os.dup2(2, 1)
  176.         saved_environ_keys = ('DEBIAN_FRONTEND', 'DEBIAN_HAS_FRONTEND', 'DEBCONF_USE_CDEBCONF')
  177.         saved_environ = { }
  178.         for key in saved_environ_keys:
  179.             if key in os.environ:
  180.                 saved_environ[key] = os.environ[key]
  181.                 continue
  182.         
  183.         os.environ['DEBIAN_FRONTEND'] = 'noninteractive'
  184.         if 'DEBIAN_HAS_FRONTEND' in os.environ:
  185.             del os.environ['DEBIAN_HAS_FRONTEND']
  186.         
  187.         if 'DEBCONF_USE_CDEBCONF' in os.environ:
  188.             del os.environ['DEBCONF_USE_CDEBCONF']
  189.         
  190.         res = pm.ResultFailed
  191.         
  192.         try:
  193.             res = pm.DoInstall(self.writefd)
  194.         finally:
  195.             os.close(self.writefd)
  196.             while True:
  197.                 
  198.                 try:
  199.                     (pid, status) = os.waitpid(child_pid, 0)
  200.                     if pid != child_pid:
  201.                         break
  202.                     
  203.                     if os.WIFEXITED(status) or os.WIFSIGNALED(status):
  204.                         break
  205.                 continue
  206.                 except OSError:
  207.                     break
  208.                     continue
  209.                 
  210.  
  211.                 None<EXCEPTION MATCH>OSError
  212.             os.dup2(saved_stdout, 1)
  213.             os.close(saved_stdout)
  214.             for key in saved_environ_keys:
  215.                 if key in saved_environ:
  216.                     os.environ[key] = saved_environ[key]
  217.                     continue
  218.                 if key in os.environ:
  219.                     del os.environ[key]
  220.                     continue
  221.             
  222.  
  223.         return res
  224.  
  225.     
  226.     def finishUpdate(self):
  227.         if self.started:
  228.             self.db.progress('STOP')
  229.             self.started = False
  230.         
  231.  
  232.  
  233.  
  234. class InstallStepError(Exception):
  235.     '''Raised when an install step fails.
  236.  
  237.     Attributes:
  238.         message -- message returned with exception
  239.  
  240.     '''
  241.     
  242.     def __init__(self, message):
  243.         Exception.__init__(self, message)
  244.         self.message = message
  245.  
  246.  
  247.  
  248. class Install:
  249.     
  250.     def __init__(self):
  251.         '''Initial attributes.'''
  252.         if os.path.isdir('/rofs'):
  253.             self.source = '/rofs'
  254.         elif os.path.isdir('/UNIONFS'):
  255.             self.source = '/UNIONFS'
  256.         else:
  257.             self.source = '/var/lib/ubiquity/source'
  258.         self.target = '/target'
  259.         self.kernel_version = platform.release()
  260.         self.db = debconf.Debconf()
  261.         apt_pkg.InitConfig()
  262.         apt_pkg.Config.Set('Dir', '/target')
  263.         apt_pkg.Config.Set('Dir::State::status', '/target/var/lib/dpkg/status')
  264.         apt_pkg.Config.Set('APT::GPGV::TrustedKeyring', '/target/etc/apt/trusted.gpg')
  265.         apt_pkg.Config.Set('Acquire::gpgv::Options::', '--ignore-time-conflict')
  266.         apt_pkg.Config.Set('DPkg::Options::', '--root=/target')
  267.         apt_pkg.Config.Clear('DPkg::Pre-Install-Pkgs')
  268.         apt_pkg.InitSystem()
  269.  
  270.     
  271.     def excepthook(self, exctype, excvalue, exctb):
  272.         '''Crash handler. Dump the traceback to a file so that it can be
  273.         read by the caller.'''
  274.         if issubclass(exctype, KeyboardInterrupt) or issubclass(exctype, SystemExit):
  275.             return None
  276.         
  277.         tbtext = ''.join(traceback.format_exception(exctype, excvalue, exctb))
  278.         syslog.syslog(syslog.LOG_ERR, 'Exception during installation:')
  279.         for line in tbtext.split('\n'):
  280.             syslog.syslog(syslog.LOG_ERR, line)
  281.         
  282.         tbfile = open('/var/lib/ubiquity/install.trace', 'w')
  283.         print >>tbfile, tbtext
  284.         tbfile.close()
  285.         sys.exit(1)
  286.  
  287.     
  288.     def run(self):
  289.         '''Run the install stage: copy everything to the target system, then
  290.         configure it as necessary.'''
  291.         self.db.progress('START', 0, 100, 'ubiquity/install/title')
  292.         self.db.progress('INFO', 'ubiquity/install/mounting_source')
  293.         
  294.         try:
  295.             if self.source == '/var/lib/ubiquity/source':
  296.                 self.mount_source()
  297.             
  298.             self.db.progress('SET', 1)
  299.             self.db.progress('REGION', 1, 75)
  300.             
  301.             try:
  302.                 self.copy_all()
  303.             except EnvironmentError:
  304.                 e = None
  305.                 if e.errno in (errno.ENOENT, errno.EIO, errno.EFAULT, errno.ENOTDIR, errno.EROFS):
  306.                     if e.filename is None:
  307.                         error_template = 'cd_hd_fault'
  308.                     elif e.filename.startswith('/target'):
  309.                         error_template = 'hd_fault'
  310.                     else:
  311.                         error_template = 'cd_fault'
  312.                     error_template = 'ubiquity/install/copying_error/%s' % error_template
  313.                     self.db.subst(error_template, 'ERROR', str(e))
  314.                     self.db.input('critical', error_template)
  315.                     self.db.go()
  316.                     sys.exit(3)
  317.                 else:
  318.                     raise 
  319.             except:
  320.                 e.errno in (errno.ENOENT, errno.EIO, errno.EFAULT, errno.ENOTDIR, errno.EROFS)
  321.  
  322.             self.db.progress('SET', 75)
  323.             self.db.progress('REGION', 75, 76)
  324.             self.db.progress('INFO', 'ubiquity/install/locales')
  325.             self.configure_locales()
  326.             self.db.progress('SET', 76)
  327.             self.db.progress('REGION', 76, 77)
  328.             self.db.progress('INFO', 'ubiquity/install/user')
  329.             self.configure_user()
  330.             self.db.progress('SET', 77)
  331.             self.db.progress('REGION', 77, 78)
  332.             self.run_target_config_hooks()
  333.             self.db.progress('SET', 78)
  334.             self.db.progress('REGION', 78, 79)
  335.             self.db.progress('INFO', 'ubiquity/install/network')
  336.             self.configure_network()
  337.             self.db.progress('SET', 79)
  338.             self.db.progress('REGION', 79, 80)
  339.             self.db.progress('INFO', 'ubiquity/install/apt')
  340.             self.configure_apt()
  341.             self.db.progress('SET', 80)
  342.             self.db.progress('REGION', 80, 85)
  343.             
  344.             try:
  345.                 self.install_language_packs()
  346.             except InstallStepError:
  347.                 pass
  348.             except IOError:
  349.                 pass
  350.             except SystemError:
  351.                 pass
  352.  
  353.             self.db.progress('SET', 85)
  354.             self.db.progress('REGION', 85, 86)
  355.             self.db.progress('INFO', 'ubiquity/install/timezone')
  356.             self.configure_timezone()
  357.             self.db.progress('SET', 86)
  358.             self.db.progress('REGION', 86, 87)
  359.             self.db.progress('INFO', 'ubiquity/install/keyboard')
  360.             self.configure_keyboard()
  361.             self.db.progress('SET', 87)
  362.             self.db.progress('REGION', 87, 88)
  363.             self.db.progress('INFO', 'ubiquity/install/migrationassistant')
  364.             self.configure_ma()
  365.             self.db.progress('SET', 88)
  366.             self.db.progress('REGION', 88, 89)
  367.             self.remove_unusable_kernels()
  368.             self.db.progress('SET', 89)
  369.             self.db.progress('REGION', 89, 93)
  370.             self.db.progress('INFO', 'ubiquity/install/hardware')
  371.             self.configure_hardware()
  372.             self.db.progress('SET', 93)
  373.             self.db.progress('REGION', 93, 94)
  374.             self.db.progress('INFO', 'ubiquity/install/bootloader')
  375.             self.configure_bootloader()
  376.             self.db.progress('SET', 94)
  377.             self.db.progress('REGION', 94, 99)
  378.             self.db.progress('INFO', 'ubiquity/install/removing')
  379.             self.remove_extras()
  380.             self.db.progress('SET', 99)
  381.             self.db.progress('INFO', 'ubiquity/install/log_files')
  382.             self.copy_logs()
  383.             self.db.progress('SET', 100)
  384.         finally:
  385.             self.cleanup()
  386.             
  387.             try:
  388.                 self.db.progress('STOP')
  389.             except (KeyboardInterrupt, SystemExit):
  390.                 raise 
  391.             except:
  392.                 pass
  393.  
  394.  
  395.  
  396.     
  397.     def copy_all(self):
  398.         '''Core copy process. This is the most important step of this
  399.         stage. It clones live filesystem into a local partition in the
  400.         selected hard disk.'''
  401.         files = []
  402.         total_size = 0
  403.         self.db.progress('START', 0, 100, 'ubiquity/install/title')
  404.         self.db.progress('INFO', 'ubiquity/install/scanning')
  405.         walklen = 0
  406.         for entry in os.walk(self.source):
  407.             walklen += 1
  408.         
  409.         walkpos = 0
  410.         walkprogress = 0
  411.         for dirpath, dirnames, filenames in os.walk(self.source):
  412.             walkpos += 1
  413.             if int((float(walkpos) / walklen) * 10) != walkprogress:
  414.                 walkprogress = int((float(walkpos) / walklen) * 10)
  415.                 self.db.progress('SET', walkprogress)
  416.             
  417.             sourcepath = dirpath[len(self.source) + 1:]
  418.             for name in dirnames + filenames:
  419.                 relpath = os.path.join(sourcepath, name)
  420.                 fqpath = os.path.join(self.source, dirpath, name)
  421.                 total_size += os.lstat(fqpath).st_size
  422.                 files.append(relpath)
  423.             
  424.         
  425.         self.db.progress('SET', 10)
  426.         self.db.progress('INFO', 'ubiquity/install/copying')
  427.         copy_progress = 0
  428.         (copied_size, counter) = (0, 0)
  429.         directory_times = []
  430.         time_start = time.time()
  431.         times = [
  432.             (time_start, copied_size)]
  433.         long_enough = False
  434.         time_last_update = time_start
  435.         old_umask = os.umask(0)
  436.         for path in files:
  437.             sourcepath = os.path.join(self.source, path)
  438.             targetpath = os.path.join(self.target, path)
  439.             st = os.lstat(sourcepath)
  440.             mode = stat.S_IMODE(st.st_mode)
  441.             if stat.S_ISLNK(st.st_mode):
  442.                 if not os.path.lexists(targetpath):
  443.                     linkto = os.readlink(sourcepath)
  444.                     os.symlink(linkto, targetpath)
  445.                 
  446.             elif stat.S_ISDIR(st.st_mode):
  447.                 if not os.path.isdir(targetpath):
  448.                     os.mkdir(targetpath, mode)
  449.                 
  450.             elif stat.S_ISCHR(st.st_mode):
  451.                 os.mknod(targetpath, stat.S_IFCHR | mode, st.st_rdev)
  452.             elif stat.S_ISBLK(st.st_mode):
  453.                 os.mknod(targetpath, stat.S_IFBLK | mode, st.st_rdev)
  454.             elif stat.S_ISFIFO(st.st_mode):
  455.                 os.mknod(targetpath, stat.S_IFIFO | mode)
  456.             elif stat.S_ISSOCK(st.st_mode):
  457.                 os.mknod(targetpath, stat.S_IFSOCK | mode)
  458.             elif stat.S_ISREG(st.st_mode):
  459.                 if not os.path.exists(targetpath):
  460.                     shutil.copyfile(sourcepath, targetpath)
  461.                 
  462.             
  463.             copied_size += st.st_size
  464.             os.lchown(targetpath, st.st_uid, st.st_gid)
  465.             if not stat.S_ISLNK(st.st_mode):
  466.                 os.chmod(targetpath, mode)
  467.             
  468.             if stat.S_ISDIR(st.st_mode):
  469.                 directory_times.append((targetpath, st.st_atime, st.st_mtime))
  470.             elif not stat.S_ISLNK(st.st_mode):
  471.                 os.utime(targetpath, (st.st_atime, st.st_mtime))
  472.             
  473.             if int(copied_size * 90 / total_size) != copy_progress:
  474.                 copy_progress = int(copied_size * 90 / total_size)
  475.                 self.db.progress('SET', 10 + copy_progress)
  476.             
  477.             time_now = time.time()
  478.             if time_now - times[-1][0] >= 0.5:
  479.                 times.append((time_now, copied_size))
  480.                 if not long_enough and time_now - times[0][0] >= 10:
  481.                     long_enough = True
  482.                 
  483.                 if long_enough and time_now - time_last_update >= 2:
  484.                     time_last_update = time_now
  485.                     while time_now - times[0][0] > 60 and time_now - times[1][0] >= 60:
  486.                         times.pop(0)
  487.                     speed = (times[-1][1] - times[0][1]) / (times[-1][0] - times[0][0])
  488.                     time_remaining = int((total_size - copied_size) / speed)
  489.                     if time_remaining < 60:
  490.                         self.db.progress('INFO', 'ubiquity/install/copying_minute')
  491.                     
  492.                 
  493.             time_now - time_last_update >= 2
  494.         
  495.         for dirtime in directory_times:
  496.             (directory, atime, mtime) = dirtime
  497.             
  498.             try:
  499.                 os.utime(directory, (atime, mtime))
  500.             continue
  501.             except OSError:
  502.                 continue
  503.             
  504.  
  505.         
  506.         os.umask(old_umask)
  507.         self.db.progress('SET', 100)
  508.         self.db.progress('STOP')
  509.  
  510.     
  511.     def copy_logs(self):
  512.         '''copy log files into installed system.'''
  513.         target_dir = os.path.join(self.target, 'var/log/installer')
  514.         if not os.path.exists(target_dir):
  515.             os.makedirs(target_dir)
  516.         
  517.         for log_file in ('/var/log/syslog', '/var/log/partman', '/var/log/installer/version'):
  518.             target_log_file = os.path.join(target_dir, os.path.basename(log_file))
  519.             if not misc.ex('cp', '-a', log_file, target_log_file):
  520.                 syslog.syslog(syslog.LOG_ERR, 'Failed to copy installation log file')
  521.             
  522.             os.chmod(target_log_file, stat.S_IRUSR | stat.S_IWUSR)
  523.         
  524.         
  525.         try:
  526.             status = open(os.path.join(self.target, 'var/lib/dpkg/status'))
  527.             status_gz = gzip.open(os.path.join(target_dir, 'initial-status.gz'), 'w')
  528.             while True:
  529.                 data = status.read(65536)
  530.                 if not data:
  531.                     break
  532.                 
  533.                 status_gz.write(data)
  534.             status_gz.close()
  535.             status.close()
  536.         except IOError:
  537.             pass
  538.  
  539.  
  540.     
  541.     def mount_one_image(self, fsfile, mountpoint = None):
  542.         if os.path.splitext(fsfile)[1] == '.cloop':
  543.             blockdev_prefix = 'cloop'
  544.         elif os.path.splitext(fsfile)[1] == '.squashfs':
  545.             blockdev_prefix = 'loop'
  546.         
  547.         if blockdev_prefix == '':
  548.             raise InstallStepError('No source device found for %s' % fsfile)
  549.         
  550.         dev = ''
  551.         sysloops = (filter,)((lambda x: x.startswith(blockdev_prefix)), os.listdir('/sys/block'))
  552.         sysloops.sort()
  553.         for sysloop in sysloops:
  554.             
  555.             try:
  556.                 sysloopf = open(os.path.join('/sys/block', sysloop, 'size'))
  557.                 sysloopsize = sysloopf.readline().strip()
  558.                 sysloopf.close()
  559.                 if sysloopsize == '0':
  560.                     devnull = open('/dev/null')
  561.                     udevinfo = subprocess.Popen([
  562.                         'udevinfo',
  563.                         '-q',
  564.                         'name',
  565.                         '-p',
  566.                         os.path.join('/block', sysloop)], stdout = subprocess.PIPE, stderr = devnull)
  567.                     devbase = udevinfo.communicate()[0]
  568.                     devnull.close()
  569.                     if udevinfo.returncode != 0:
  570.                         devbase = sysloop
  571.                     
  572.                     dev = '/dev/%s' % devbase
  573.                     break
  574.             continue
  575.             continue
  576.             continue
  577.  
  578.         
  579.         if dev == '':
  580.             raise InstallStepError('No loop device available for %s' % fsfile)
  581.         
  582.         misc.ex('losetup', dev, fsfile)
  583.         if mountpoint is None:
  584.             mountpoint = '/var/lib/ubiquity/%s' % sysloop
  585.         
  586.         if not os.path.isdir(mountpoint):
  587.             os.mkdir(mountpoint)
  588.         
  589.         misc.ex('mount', dev, mountpoint)
  590.         return (dev, mountpoint)
  591.  
  592.     
  593.     def mount_source(self):
  594.         '''mounting loop system from cloop or squashfs system.'''
  595.         self.devs = []
  596.         self.mountpoints = []
  597.         if not os.path.isdir(self.source):
  598.             syslog.syslog('mkdir %s' % self.source)
  599.             os.mkdir(self.source)
  600.         
  601.         fs_preseed = self.db.get('ubiquity/install/filesystem-images')
  602.         if fs_preseed == '':
  603.             mounts = open('/proc/mounts')
  604.             for line in mounts:
  605.                 (device, fstype) = line.split()[1:3]
  606.                 if fstype == 'squashfs' and os.path.exists(device):
  607.                     misc.ex('mount', '--bind', device, self.source)
  608.                     self.mountpoints.append(self.source)
  609.                     mounts.close()
  610.                     return None
  611.                     continue
  612.             
  613.             mounts.close()
  614.             fsfiles = [
  615.                 '/cdrom/casper/filesystem.cloop',
  616.                 '/cdrom/casper/filesystem.squashfs',
  617.                 '/cdrom/META/META.squashfs']
  618.             for fsfile in fsfiles:
  619.                 if fsfile != '' and os.path.isfile(fsfile):
  620.                     (dev, mountpoint) = self.mount_one_image(fsfile, self.source)
  621.                     self.devs.append(dev)
  622.                     self.mountpoints.append(mountpoint)
  623.                     continue
  624.             
  625.         elif len(fs_preseed.split()) == 1:
  626.             if not os.path.isfile(fs_preseed):
  627.                 raise InstallStepError('Preseeded filesystem image %s not found' % fs_preseed)
  628.                 (dev, mountpoint) = self.mount_one_image(fsfile, self.source)
  629.                 self.devs.append(dev)
  630.                 self.mountpoints.append(mountpoint)
  631.             
  632.         else:
  633.             for fsfile in fs_preseed.split():
  634.                 if not os.path.isfile(fsfile):
  635.                     raise InstallStepError('Preseeded filesystem image %s not found' % fsfile)
  636.                 
  637.                 (dev, mountpoint) = self.mount_one_image(fsfile)
  638.                 self.devs.append(dev)
  639.                 self.mountpoints.append(mountpoint)
  640.             
  641.             if not self.devs:
  642.                 raise AssertionError
  643.             if not self.mountpoints:
  644.                 raise AssertionError
  645.             misc.ex('mount', '-t', 'unionfs', '-o', 'dirs=' + map((lambda x: '%s=ro' % x), self.mountpoints), 'unionfs', self.source)
  646.             self.mountpoints.append(self.source)
  647.  
  648.     
  649.     def umount_source(self):
  650.         '''umounting loop system from cloop or squashfs system.'''
  651.         devs = self.devs
  652.         devs.reverse()
  653.         mountpoints = self.mountpoints
  654.         mountpoints.reverse()
  655.         for mountpoint in mountpoints:
  656.             if not misc.ex('umount', mountpoint):
  657.                 raise InstallStepError('Failed to unmount %s' % mountpoint)
  658.                 continue
  659.         
  660.         for dev in devs:
  661.             if dev != '' and not misc.ex('losetup', '-d', dev):
  662.                 raise InstallStepError('Failed to detach loopback device %s' % dev)
  663.                 continue
  664.         
  665.  
  666.     
  667.     def chroot_setup(self):
  668.         '''Set up /target for safe package management operations.'''
  669.         policy_rc_d = os.path.join(self.target, 'usr/sbin/policy-rc.d')
  670.         f = open(policy_rc_d, 'w')
  671.         print >>f, '#!/bin/sh\nexit 101'
  672.         f.close()
  673.         os.chmod(policy_rc_d, 493)
  674.         start_stop_daemon = os.path.join(self.target, 'sbin/start-stop-daemon')
  675.         if os.path.exists(start_stop_daemon):
  676.             os.rename(start_stop_daemon, '%s.REAL' % start_stop_daemon)
  677.         
  678.         f = open(start_stop_daemon, 'w')
  679.         print >>f, "#!/bin/sh\necho 1>&2\necho 'Warning: Fake start-stop-daemon called, doing nothing.' 1>&2\nexit 0"
  680.         f.close()
  681.         os.chmod(start_stop_daemon, 493)
  682.         if not os.path.exists(os.path.join(self.target, 'proc/cmdline')):
  683.             self.chrex('mount', '-t', 'proc', 'proc', '/proc')
  684.         
  685.         if not os.path.exists(os.path.join(self.target, 'sys/devices')):
  686.             self.chrex('mount', '-t', 'sysfs', 'sysfs', '/sys')
  687.         
  688.  
  689.     
  690.     def chroot_cleanup(self):
  691.         '''Undo the work done by chroot_setup.'''
  692.         self.chrex('umount', '/sys')
  693.         self.chrex('umount', '/proc')
  694.         start_stop_daemon = os.path.join(self.target, 'sbin/start-stop-daemon')
  695.         os.rename('%s.REAL' % start_stop_daemon, start_stop_daemon)
  696.         policy_rc_d = os.path.join(self.target, 'usr/sbin/policy-rc.d')
  697.         os.unlink(policy_rc_d)
  698.  
  699.     
  700.     def run_target_config_hooks(self):
  701.         '''Run hook scripts from /usr/lib/ubiquity/target-config. This allows
  702.         casper to hook into us and repeat bits of its configuration in the
  703.         target system.'''
  704.         hookdir = '/usr/lib/ubiquity/target-config'
  705.         if os.path.isdir(hookdir):
  706.             hooks = filter((lambda entry: '.' not in entry), os.listdir(hookdir))
  707.             self.db.progress('START', 0, len(hooks), 'ubiquity/install/title')
  708.             self.db.progress('INFO', 'ubiquity/install/target_hooks')
  709.             for hookentry in hooks:
  710.                 hook = os.path.join(hookdir, hookentry)
  711.                 if not os.access(hook, os.X_OK):
  712.                     self.db.progress('STEP', 1)
  713.                     continue
  714.                 
  715.                 subprocess.call([
  716.                     'log-output',
  717.                     '-t',
  718.                     'ubiquity',
  719.                     '--pass-stdout',
  720.                     hook])
  721.                 self.db.progress('STEP', 1)
  722.             
  723.             self.db.progress('STOP')
  724.         
  725.  
  726.     
  727.     def configure_locales(self):
  728.         '''Apply locale settings to installed system.'''
  729.         dbfilter = language_apply.LanguageApply(None)
  730.         ret = dbfilter.run_command(auto_process = True)
  731.         if ret != 0:
  732.             raise InstallStepError('LanguageApply failed with code %d' % ret)
  733.         
  734.         self.chrex('fontconfig-voodoo', '--auto', '--quiet')
  735.  
  736.     
  737.     def configure_apt(self):
  738.         '''Configure /etc/apt/sources.list.'''
  739.         apt_conf_itc = open(os.path.join(self.target, 'etc/apt/apt.conf.d/00IgnoreTimeConflict'), 'w')
  740.         print >>apt_conf_itc, 'Acquire::gpgv::Options { "--ignore-time-conflict"; };'
  741.         apt_conf_itc.close()
  742.         dbfilter = apt_setup.AptSetup(None)
  743.         ret = dbfilter.run_command(auto_process = True)
  744.         if ret != 0:
  745.             raise InstallStepError('AptSetup failed with code %d' % ret)
  746.         
  747.  
  748.     
  749.     def get_cache_pkg(self, cache, pkg):
  750.         
  751.         try:
  752.             return cache[pkg]
  753.         except KeyError:
  754.             return None
  755.  
  756.  
  757.     
  758.     def record_installed(self, pkgs):
  759.         """Record which packages we've explicitly installed so that we don't
  760.         try to remove them later."""
  761.         record_file = '/var/lib/ubiquity/apt-installed'
  762.         if not os.path.exists(os.path.dirname(record_file)):
  763.             os.makedirs(os.path.dirname(record_file))
  764.         
  765.         record = open(record_file, 'a')
  766.         for pkg in pkgs:
  767.             print >>record, pkg
  768.         
  769.         record.close()
  770.  
  771.     
  772.     def mark_install(self, cache, pkg):
  773.         cachedpkg = self.get_cache_pkg(cache, pkg)
  774.         if cachedpkg is not None and not (cachedpkg.isInstalled):
  775.             apt_error = False
  776.             
  777.             try:
  778.                 cachedpkg.markInstall()
  779.             except SystemError:
  780.                 apt_error = True
  781.  
  782.             if cache._depcache.BrokenCount > 0 or apt_error:
  783.                 brokenpkgs = self.broken_packages(cache)
  784.                 while brokenpkgs:
  785.                     for brokenpkg in brokenpkgs:
  786.                         self.get_cache_pkg(cache, brokenpkg).markKeep()
  787.                     
  788.                     new_brokenpkgs = self.broken_packages(cache)
  789.                     if brokenpkgs == new_brokenpkgs:
  790.                         break
  791.                     
  792.                     brokenpkgs = new_brokenpkgs
  793.                 if not cache._depcache.BrokenCount == 0:
  794.                     raise AssertionError
  795.             
  796.         
  797.  
  798.     
  799.     def install_language_packs(self):
  800.         langpacks = []
  801.         
  802.         try:
  803.             langpack_db = self.db.get('pkgsel/language-packs')
  804.             langpacks = langpack_db.replace(',', '').split()
  805.         except debconf.DebconfError:
  806.             pass
  807.  
  808.         if not langpacks:
  809.             
  810.             try:
  811.                 langpack_db = self.db.get('localechooser/supported-locales')
  812.                 langpack_set = set()
  813.                 for locale in langpack_db.replace(',', '').split():
  814.                     langpack_set.add(locale.split('_')[0])
  815.                 
  816.                 langpacks = sorted(langpack_set)
  817.             except debconf.DebconfError:
  818.                 pass
  819.             except:
  820.                 None<EXCEPTION MATCH>debconf.DebconfError
  821.             
  822.  
  823.         None<EXCEPTION MATCH>debconf.DebconfError
  824.         if not langpacks:
  825.             langpack_db = self.db.get('debian-installer/locale')
  826.             langpacks = [
  827.                 langpack_db.split('_')[0]]
  828.         
  829.         syslog.syslog('keeping language packs for: %s' % ' '.join(langpacks))
  830.         
  831.         try:
  832.             lppatterns = self.db.get('pkgsel/language-pack-patterns').split()
  833.         except debconf.DebconfError:
  834.             return None
  835.  
  836.         to_install = []
  837.         for lp in langpacks:
  838.             to_install.append('language-pack-%s' % lp)
  839.             for pattern in lppatterns:
  840.                 to_install.append(pattern.replace('$LL', lp))
  841.             
  842.             to_install.append('language-support-%s' % lp)
  843.         
  844.         self.record_installed(to_install)
  845.         self.db.progress('START', 0, 100, 'ubiquity/langpacks/title')
  846.         self.db.progress('REGION', 0, 10)
  847.         fetchprogress = DebconfFetchProgress(self.db, 'ubiquity/langpacks/title', 'ubiquity/install/apt_indices_starting', 'ubiquity/install/apt_indices')
  848.         cache = Cache()
  849.         if cache._depcache.BrokenCount > 0:
  850.             syslog.syslog('not installing language packs, since there are broken packages: %s' % ', '.join(self.broken_packages(cache)))
  851.             self.db.progress('STOP')
  852.             return None
  853.         
  854.         
  855.         try:
  856.             if cache.update(fetchprogress) not in (0, True):
  857.                 fetchprogress.stop()
  858.                 self.db.progress('STOP')
  859.                 return None
  860.         except IOError:
  861.             e = None
  862.             for line in str(e).split('\n'):
  863.                 syslog.syslog(syslog.LOG_WARNING, line)
  864.             
  865.             self.db.progress('STOP')
  866.             raise 
  867.  
  868.         cache.open(None)
  869.         self.db.progress('SET', 10)
  870.         self.db.progress('REGION', 10, 100)
  871.         fetchprogress = DebconfFetchProgress(self.db, 'ubiquity/langpacks/title', None, 'ubiquity/langpacks/packages')
  872.         installprogress = DebconfInstallProgress(self.db, 'ubiquity/langpacks/title', 'ubiquity/install/apt_info')
  873.         for lp in to_install:
  874.             self.mark_install(cache, lp)
  875.         
  876.         installed_pkgs = []
  877.         for pkg in cache.keys():
  878.             if cache[pkg].markedInstall and cache[pkg].markedUpgrade and cache[pkg].markedReinstall or cache[pkg].markedDowngrade:
  879.                 installed_pkgs.append(pkg)
  880.                 continue
  881.         
  882.         self.record_installed(installed_pkgs)
  883.         commit_error = None
  884.         
  885.         try:
  886.             if not cache.commit(fetchprogress, installprogress):
  887.                 fetchprogress.stop()
  888.                 installprogress.finishUpdate()
  889.                 self.db.progress('STOP')
  890.                 return None
  891.         except IOError:
  892.             e = None
  893.             for line in str(e).split('\n'):
  894.                 syslog.syslog(syslog.LOG_WARNING, line)
  895.             
  896.             commit_error = str(e)
  897.         except SystemError:
  898.             e = None
  899.             for line in str(e).split('\n'):
  900.                 syslog.syslog(syslog.LOG_WARNING, line)
  901.             
  902.             commit_error = str(e)
  903.  
  904.         self.db.progress('SET', 100)
  905.         cache.open(None)
  906.         if commit_error or cache._depcache.BrokenCount > 0:
  907.             if commit_error is None:
  908.                 commit_error = ''
  909.             
  910.             brokenpkgs = self.broken_packages(cache)
  911.             syslog.syslog('broken packages after language pack installation: %s' % ', '.join(brokenpkgs))
  912.             self.db.subst('ubiquity/install/broken_install', 'ERROR', commit_error)
  913.             self.db.subst('ubiquity/install/broken_install', 'PACKAGES', ', '.join(brokenpkgs))
  914.             self.db.input('critical', 'ubiquity/install/broken_install')
  915.             self.db.go()
  916.         
  917.         self.db.progress('STOP')
  918.  
  919.     
  920.     def configure_timezone(self):
  921.         '''Set timezone on installed system.'''
  922.         dbfilter = timezone_apply.TimezoneApply(None)
  923.         ret = dbfilter.run_command(auto_process = True)
  924.         if ret != 0:
  925.             raise InstallStepError('TimezoneApply failed with code %d' % ret)
  926.         
  927.         dbfilter = clock_setup.ClockSetup(None)
  928.         ret = dbfilter.run_command(auto_process = True)
  929.         if ret != 0:
  930.             raise InstallStepError('ClockSetup failed with code %d' % ret)
  931.         
  932.  
  933.     
  934.     def configure_keyboard(self):
  935.         '''Set keyboard in installed system.'''
  936.         dbfilter = console_setup_apply.ConsoleSetupApply(None)
  937.         ret = dbfilter.run_command(auto_process = True)
  938.         if ret != 0:
  939.             raise InstallStepError('ConsoleSetupApply failed with code %d' % ret)
  940.         
  941.  
  942.     
  943.     def configure_user(self):
  944.         '''create the user selected along the installation process
  945.         into the installed system. Default user from live system is
  946.         deleted and skel for this new user is copied to $HOME.'''
  947.         dbfilter = usersetup_apply.UserSetupApply(None)
  948.         ret = dbfilter.run_command(auto_process = True)
  949.         if ret != 0:
  950.             raise InstallStepError('UserSetupApply failed with code %d' % ret)
  951.         
  952.  
  953.     
  954.     def configure_ma(self):
  955.         '''import documents, settings, and users from previous operating
  956.         systems.'''
  957.         if 'UBIQUITY_MIGRATION_ASSISTANT' in os.environ:
  958.             dbfilter = migrationassistant_apply.MigrationAssistantApply(None)
  959.             ret = dbfilter.run_command(auto_process = True)
  960.             if ret != 0:
  961.                 raise InstallStepError('MigrationAssistantApply failed with code %d' % ret)
  962.             
  963.         
  964.  
  965.     
  966.     def get_resume_partition(self):
  967.         biggest_size = 0
  968.         biggest_partition = None
  969.         swaps = open('/proc/swaps')
  970.         for line in swaps:
  971.             words = line.split()
  972.             if words[1] != 'partition':
  973.                 continue
  974.             
  975.             size = int(words[2])
  976.             if size > biggest_size:
  977.                 biggest_size = size
  978.                 biggest_partition = words[0]
  979.                 continue
  980.         
  981.         swaps.close()
  982.         return biggest_partition
  983.  
  984.     
  985.     def configure_hardware(self):
  986.         '''reconfiguring several packages which depends on the
  987.         hardware system in which has been installed on and need some
  988.         automatic configurations to get work.'''
  989.         self.chroot_setup()
  990.         
  991.         try:
  992.             dbfilter = hw_detect.HwDetect(None, self.db)
  993.             ret = dbfilter.run_command(auto_process = True)
  994.             if ret != 0:
  995.                 raise InstallStepError('HwDetect failed with code %d' % ret)
  996.         finally:
  997.             self.chroot_cleanup()
  998.  
  999.         self.db.progress('INFO', 'ubiquity/install/hardware')
  1000.         misc.ex('/usr/lib/ubiquity/debian-installer-utils/register-module.post-base-installer')
  1001.         resume = self.get_resume_partition()
  1002.         if resume is not None:
  1003.             resume_uuid = None
  1004.             
  1005.             try:
  1006.                 resume_uuid = subprocess.Popen([
  1007.                     'vol_id',
  1008.                     '-u',
  1009.                     resume], stdout = subprocess.PIPE).communicate()[0].rstrip('\n')
  1010.             except OSError:
  1011.                 pass
  1012.  
  1013.             if resume_uuid:
  1014.                 resume = 'UUID=%s' % resume_uuid
  1015.             
  1016.             if os.path.exists(os.path.join(self.target, 'etc/initramfs-tools/conf.d')):
  1017.                 configdir = os.path.join(self.target, 'etc/initramfs-tools/conf.d')
  1018.             elif os.path.exists(os.path.join(self.target, 'etc/mkinitramfs/conf.d')):
  1019.                 configdir = os.path.join(self.target, 'etc/mkinitramfs/conf.d')
  1020.             else:
  1021.                 configdir = None
  1022.             if configdir is not None:
  1023.                 configfile = open(os.path.join(configdir, 'resume'), 'w')
  1024.                 print >>configfile, 'RESUME=%s' % resume
  1025.                 configfile.close()
  1026.             
  1027.         
  1028.         
  1029.         try:
  1030.             os.unlink('/target/etc/usplash.conf')
  1031.         except OSError:
  1032.             pass
  1033.  
  1034.         
  1035.         try:
  1036.             os.unlink('/target/etc/popularity-contest.conf')
  1037.         except OSError:
  1038.             pass
  1039.  
  1040.         
  1041.         try:
  1042.             participate = self.db.get('popularity-contest/participate')
  1043.             self.set_debconf('popularity-contest/participate', participate)
  1044.         except debconf.DebconfError:
  1045.             pass
  1046.  
  1047.         self.chroot_setup()
  1048.         self.chrex('dpkg-divert', '--package', 'ubiquity', '--rename', '--quiet', '--add', '/usr/sbin/update-initramfs')
  1049.         
  1050.         try:
  1051.             os.symlink('/bin/true', '/target/usr/sbin/update-initramfs')
  1052.         except OSError:
  1053.             pass
  1054.  
  1055.         packages = [
  1056.             'linux-image-' + self.kernel_version,
  1057.             'linux-restricted-modules-' + self.kernel_version,
  1058.             'usplash',
  1059.             'popularity-contest']
  1060.         
  1061.         try:
  1062.             for package in packages:
  1063.                 self.reconfigure(package)
  1064.         finally:
  1065.             
  1066.             try:
  1067.                 os.unlink('/target/usr/sbin/update-initramfs')
  1068.             except OSError:
  1069.                 pass
  1070.  
  1071.             self.chrex('dpkg-divert', '--package', 'ubiquity', '--rename', '--quiet', '--remove', '/usr/sbin/update-initramfs')
  1072.             self.chrex('update-initramfs', '-c', '-k', os.uname()[2])
  1073.             self.chroot_cleanup()
  1074.  
  1075.         bootdir = os.path.join(self.target, 'boot')
  1076.         if self.db.get('base-installer/kernel/linux/link_in_boot') == 'true':
  1077.             linkdir = bootdir
  1078.             linkprefix = ''
  1079.         else:
  1080.             linkdir = self.target
  1081.             linkprefix = 'boot'
  1082.         re_symlink = re.compile('vmlinu[xz]|initrd.img$')
  1083.         for entry in os.listdir(linkdir):
  1084.             if re_symlink.match(entry) is not None:
  1085.                 filename = os.path.join(linkdir, entry)
  1086.                 if os.path.islink(filename):
  1087.                     os.unlink(filename)
  1088.                 
  1089.             os.path.islink(filename)
  1090.         
  1091.         if linkdir != self.target:
  1092.             for entry in os.listdir(self.target):
  1093.                 if re_symlink.match(entry) is not None:
  1094.                     filename = os.path.join(self.target, entry)
  1095.                     if os.path.islink(filename):
  1096.                         os.unlink(filename)
  1097.                     
  1098.                 os.path.islink(filename)
  1099.             
  1100.         
  1101.         re_image = re.compile('(vmlinu[xz]|initrd.img)-')
  1102.         for entry in os.listdir(bootdir):
  1103.             match = re_image.match(entry)
  1104.             if match is not None:
  1105.                 imagetype = match.group(1)
  1106.                 linksrc = os.path.join(linkprefix, entry)
  1107.                 linkdst = os.path.join(linkdir, imagetype)
  1108.                 if os.path.exists(linkdst):
  1109.                     if entry.endswith('-' + self.kernel_version):
  1110.                         os.unlink(linkdst)
  1111.                     
  1112.                 
  1113.                 os.symlink(linksrc, linkdst)
  1114.                 continue
  1115.         
  1116.  
  1117.     
  1118.     def get_all_interfaces(self):
  1119.         '''Get all non-local network interfaces.'''
  1120.         ifs = []
  1121.         ifs_file = open('/proc/net/dev')
  1122.         ifs_file.readline()
  1123.         ifs_file.readline()
  1124.         for line in ifs_file:
  1125.             name = re.match('(.*?(?::\\d+)?):', line.strip()).group(1)
  1126.             if name == 'lo':
  1127.                 continue
  1128.             
  1129.             ifs.append(name)
  1130.         
  1131.         ifs_file.close()
  1132.         return ifs
  1133.  
  1134.     
  1135.     def configure_network(self):
  1136.         """Automatically configure the network.
  1137.         
  1138.         At present, the only thing the user gets to tweak in the UI is the
  1139.         hostname. Some other things will be copied from the live filesystem,
  1140.         so changes made there will be reflected in the installed system.
  1141.         
  1142.         Unfortunately, at present we have to duplicate a fair bit of netcfg
  1143.         here, because it's hard to drive netcfg in a way that won't try to
  1144.         bring interfaces up and down."""
  1145.         for path in ('/etc/network/interfaces', '/etc/resolv.conf'):
  1146.             if os.path.exists(path):
  1147.                 shutil.copy2(path, os.path.join(self.target, path[1:]))
  1148.                 continue
  1149.         
  1150.         
  1151.         try:
  1152.             hostname = self.db.get('netcfg/get_hostname')
  1153.         except debconf.DebconfError:
  1154.             hostname = ''
  1155.  
  1156.         
  1157.         try:
  1158.             domain = self.db.get('netcfg/get_domain')
  1159.         except debconf.DebconfError:
  1160.             domain = ''
  1161.  
  1162.         if hostname == '':
  1163.             hostname = 'ubuntu'
  1164.         
  1165.         fp = open(os.path.join(self.target, 'etc/hostname'), 'w')
  1166.         print >>fp, hostname
  1167.         fp.close()
  1168.         hosts = open(os.path.join(self.target, 'etc/hosts'), 'w')
  1169.         print >>hosts, '127.0.0.1\tlocalhost'
  1170.         if domain:
  1171.             print >>hosts, '127.0.1.1\t%s.%s\t%s' % (hostname, domain, hostname)
  1172.         else:
  1173.             print >>hosts, '127.0.1.1\t%s' % hostname
  1174.         print >>hosts, textwrap.dedent('\n            # The following lines are desirable for IPv6 capable hosts\n            ::1     ip6-localhost ip6-loopback\n            fe00::0 ip6-localnet\n            ff00::0 ip6-mcastprefix\n            ff02::1 ip6-allnodes\n            ff02::2 ip6-allrouters\n            ff02::3 ip6-allhosts')
  1175.         hosts.close()
  1176.         SIOCGIFHWADDR = 35111
  1177.         ARPHRD_ETHER = 1
  1178.         if_names = { }
  1179.         sock = socket.socket(socket.SOCK_DGRAM)
  1180.         interfaces = self.get_all_interfaces()
  1181.         for i in range(len(interfaces)):
  1182.             if_names[interfaces[i]] = struct.unpack('H6s', fcntl.ioctl(sock.fileno(), SIOCGIFHWADDR, struct.pack('256s', interfaces[i]))[16:24])
  1183.         
  1184.         sock.close()
  1185.         iftab = open(os.path.join(self.target, 'etc/iftab'), 'w')
  1186.         print >>iftab, textwrap.dedent('            # This file assigns persistent names to network interfaces.\n            # See iftab(5) for syntax.\n            ')
  1187.         for i in range(len(interfaces)):
  1188.             dup = False
  1189.             with_arp = False
  1190.             if_name = if_names[interfaces[i]]
  1191.             if if_name is None or if_name[0] != ARPHRD_ETHER:
  1192.                 continue
  1193.             
  1194.             for j in range(len(interfaces)):
  1195.                 if i == j or if_names[interfaces[j]] is None:
  1196.                     continue
  1197.                 
  1198.                 if if_name[1] != if_names[interfaces[j]][1]:
  1199.                     continue
  1200.                 
  1201.                 if if_names[interfaces[j]][0] == ARPHRD_ETHER:
  1202.                     dup = True
  1203.                     continue
  1204.             
  1205.             if dup:
  1206.                 continue
  1207.             
  1208.             line = [] + []([ '%02x' % ord(if_name[1][c]) for c in range(6) ])
  1209.             line += ' arp %d' % if_name[0]
  1210.             print >>iftab, line
  1211.         
  1212.         iftab.close()
  1213.  
  1214.     
  1215.     def configure_bootloader(self):
  1216.         '''configuring and installing boot loader into installed
  1217.         hardware system.'''
  1218.         misc.ex('mount', '--bind', '/proc', self.target + '/proc')
  1219.         misc.ex('mount', '--bind', '/dev', self.target + '/dev')
  1220.         archdetect = subprocess.Popen([
  1221.             'archdetect'], stdout = subprocess.PIPE)
  1222.         subarch = archdetect.communicate()[0].strip()
  1223.         
  1224.         try:
  1225.             if subarch.startswith('amd64/') or subarch.startswith('i386/'):
  1226.                 grubinstaller = grubinstaller
  1227.                 import ubiquity.components
  1228.                 dbfilter = grubinstaller.GrubInstaller(None)
  1229.                 ret = dbfilter.run_command(auto_process = True)
  1230.                 if ret != 0:
  1231.                     raise InstallStepError('GrubInstaller failed with code %d' % ret)
  1232.                 
  1233.             elif subarch == 'powerpc/ps3':
  1234.                 kbootinstaller = kbootinstaller
  1235.                 import ubiquity.components
  1236.                 dbfilter = kbootinstaller.KbootInstaller(None)
  1237.                 ret = dbfilter.run_command(auto_process = True)
  1238.                 if ret != 0:
  1239.                     raise InstallStepError('KbootInstaller failed with code %d' % ret)
  1240.                 
  1241.             elif subarch.startswith('powerpc/'):
  1242.                 yabootinstaller = yabootinstaller
  1243.                 import ubiquity.components
  1244.                 dbfilter = yabootinstaller.YabootInstaller(None)
  1245.                 ret = dbfilter.run_command(auto_process = True)
  1246.                 if ret != 0:
  1247.                     raise InstallStepError('YabootInstaller failed with code %d' % ret)
  1248.                 
  1249.             else:
  1250.                 raise InstallStepError('No bootloader installer found')
  1251.         except ImportError:
  1252.             raise InstallStepError('No bootloader installer found')
  1253.  
  1254.         misc.ex('umount', '-f', self.target + '/proc')
  1255.         misc.ex('umount', '-f', self.target + '/dev')
  1256.  
  1257.     
  1258.     def broken_packages(self, cache):
  1259.         brokenpkgs = set()
  1260.         for pkg in cache.keys():
  1261.             
  1262.             try:
  1263.                 if cache._depcache.IsInstBroken(cache._cache[pkg]):
  1264.                     brokenpkgs.add(pkg)
  1265.             continue
  1266.             except KeyError:
  1267.                 continue
  1268.                 continue
  1269.             
  1270.  
  1271.         
  1272.         return brokenpkgs
  1273.  
  1274.     
  1275.     def do_remove(self, to_remove, recursive = False):
  1276.         self.db.progress('START', 0, 5, 'ubiquity/install/title')
  1277.         self.db.progress('INFO', 'ubiquity/install/find_removables')
  1278.         fetchprogress = DebconfFetchProgress(self.db, 'ubiquity/install/title', 'ubiquity/install/apt_indices_starting', 'ubiquity/install/apt_indices')
  1279.         cache = Cache()
  1280.         if cache._depcache.BrokenCount > 0:
  1281.             syslog.syslog('not processing removals, since there are broken packages: %s' % ', '.join(self.broken_packages(cache)))
  1282.             self.db.progress('STOP')
  1283.             return None
  1284.         
  1285.         while True:
  1286.             removed = set()
  1287.             for pkg in to_remove:
  1288.                 cachedpkg = self.get_cache_pkg(cache, pkg)
  1289.                 if cachedpkg is not None and cachedpkg.isInstalled:
  1290.                     apt_error = False
  1291.                     
  1292.                     try:
  1293.                         cachedpkg.markDelete(autoFix = False, purge = True)
  1294.                     except SystemError:
  1295.                         apt_error = True
  1296.  
  1297.                     if apt_error:
  1298.                         cachedpkg.markKeep()
  1299.                     elif cache._depcache.BrokenCount > 0:
  1300.                         brokenpkgs = self.broken_packages(cache)
  1301.                         broken_removed = set()
  1302.                         while brokenpkgs:
  1303.                             if recursive or brokenpkgs <= to_remove:
  1304.                                 broken_removed_inner = set()
  1305.                                 for pkg2 in brokenpkgs:
  1306.                                     cachedpkg2 = self.get_cache_pkg(cache, pkg2)
  1307.                                     if cachedpkg2 is not None:
  1308.                                         broken_removed_inner.add(pkg2)
  1309.                                         
  1310.                                         try:
  1311.                                             cachedpkg2.markDelete(autoFix = False, purge = True)
  1312.                                         except SystemError:
  1313.                                             apt_error = True
  1314.                                             break
  1315.                                         except:
  1316.                                             None<EXCEPTION MATCH>SystemError
  1317.                                         
  1318.  
  1319.                                     None<EXCEPTION MATCH>SystemError
  1320.                                 
  1321.                                 broken_removed |= broken_removed_inner
  1322.                                 if apt_error or not broken_removed_inner:
  1323.                                     break
  1324.                                 
  1325.                                 brokenpkgs = self.broken_packages(cache)
  1326.                                 continue
  1327.                     if apt_error or cache._depcache.BrokenCount > 0:
  1328.                         for pkg2 in broken_removed:
  1329.                             self.get_cache_pkg(cache, pkg2).markKeep()
  1330.                         
  1331.                         cachedpkg.markKeep()
  1332.                     else:
  1333.                         removed.add(pkg)
  1334.                         removed |= broken_removed
  1335.                 else:
  1336.                     removed.add(pkg)
  1337.                 if not cache._depcache.BrokenCount == 0:
  1338.                     raise AssertionError
  1339.             
  1340.             if not removed:
  1341.                 break
  1342.             
  1343.             to_remove -= removed
  1344.         self.db.progress('SET', 1)
  1345.         self.db.progress('REGION', 1, 5)
  1346.         fetchprogress = DebconfFetchProgress(self.db, 'ubiquity/install/title', None, 'ubiquity/install/fetch_remove')
  1347.         installprogress = DebconfInstallProgress(self.db, 'ubiquity/install/title', 'ubiquity/install/apt_info', 'ubiquity/install/apt_error_remove')
  1348.         self.chroot_setup()
  1349.         commit_error = None
  1350.         
  1351.         try:
  1352.             if not cache.commit(fetchprogress, installprogress):
  1353.                 fetchprogress.stop()
  1354.                 installprogress.finishUpdate()
  1355.                 self.db.progress('STOP')
  1356.                 return None
  1357.         except SystemError:
  1358.             e = None
  1359.             for line in str(e).split('\n'):
  1360.                 syslog.syslog(syslog.LOG_ERR, line)
  1361.             
  1362.             commit_error = str(e)
  1363.         finally:
  1364.             self.chroot_cleanup()
  1365.  
  1366.         self.db.progress('SET', 5)
  1367.         cache.open(None)
  1368.         if commit_error or cache._depcache.BrokenCount > 0:
  1369.             if commit_error is None:
  1370.                 commit_error = ''
  1371.             
  1372.             brokenpkgs = self.broken_packages(cache)
  1373.             syslog.syslog('broken packages after removal: %s' % ', '.join(brokenpkgs))
  1374.             self.db.subst('ubiquity/install/broken_remove', 'ERROR', commit_error)
  1375.             self.db.subst('ubiquity/install/broken_remove', 'PACKAGES', ', '.join(brokenpkgs))
  1376.             self.db.input('critical', 'ubiquity/install/broken_remove')
  1377.             self.db.go()
  1378.         
  1379.         self.db.progress('STOP')
  1380.  
  1381.     
  1382.     def remove_unusable_kernels(self):
  1383.         '''Remove unusable kernels; keeping them may cause us to be unable
  1384.         to boot.'''
  1385.         self.db.progress('START', 0, 5, 'ubiquity/install/title')
  1386.         self.db.progress('INFO', 'ubiquity/install/find_removables')
  1387.         dbfilter = check_kernels.CheckKernels(None)
  1388.         dbfilter.run_command(auto_process = True)
  1389.         remove_kernels = set()
  1390.         if os.path.exists('/var/lib/ubiquity/remove-kernels'):
  1391.             remove_kernels_file = open('/var/lib/ubiquity/remove-kernels')
  1392.             for line in remove_kernels_file:
  1393.                 remove_kernels.add(line.strip())
  1394.             
  1395.             remove_kernels_file.close()
  1396.         
  1397.         if len(remove_kernels) == 0:
  1398.             self.db.progress('STOP')
  1399.             return None
  1400.         
  1401.         self.db.progress('SET', 1)
  1402.         self.db.progress('REGION', 1, 5)
  1403.         
  1404.         try:
  1405.             self.do_remove(remove_kernels, recursive = True)
  1406.         except:
  1407.             self.db.progress('STOP')
  1408.             raise 
  1409.  
  1410.         self.db.progress('SET', 5)
  1411.         self.db.progress('STOP')
  1412.  
  1413.     
  1414.     def remove_extras(self):
  1415.         '''Try to remove packages that are needed on the live CD but not on
  1416.         the installed system.'''
  1417.         if os.path.exists('/cdrom/casper/filesystem.manifest-desktop') and os.path.exists('/cdrom/casper/filesystem.manifest'):
  1418.             desktop_packages = set()
  1419.             manifest = open('/cdrom/casper/filesystem.manifest-desktop')
  1420.             for line in manifest:
  1421.                 if line.strip() != '' and not line.startswith('#'):
  1422.                     desktop_packages.add(line.split()[0])
  1423.                     continue
  1424.             
  1425.             manifest.close()
  1426.             live_packages = set()
  1427.             manifest = open('/cdrom/casper/filesystem.manifest')
  1428.             for line in manifest:
  1429.                 if line.strip() != '' and not line.startswith('#'):
  1430.                     live_packages.add(line.split()[0])
  1431.                     continue
  1432.             
  1433.             manifest.close()
  1434.             difference = live_packages - desktop_packages
  1435.         else:
  1436.             difference = set()
  1437.         apt_installed = set()
  1438.         if os.path.exists('/var/lib/ubiquity/apt-installed'):
  1439.             apt_installed_file = open('/var/lib/ubiquity/apt-installed')
  1440.             for line in apt_installed_file:
  1441.                 apt_installed.add(line.strip())
  1442.             
  1443.             apt_installed_file.close()
  1444.         
  1445.         difference -= apt_installed
  1446.         if len(difference) == 0:
  1447.             return None
  1448.         
  1449.         self.do_remove(difference)
  1450.  
  1451.     
  1452.     def cleanup(self):
  1453.         '''Miscellaneous cleanup tasks.'''
  1454.         
  1455.         try:
  1456.             os.unlink(os.path.join(self.target, 'etc/apt/apt.conf.d/00IgnoreTimeConflict'))
  1457.         except:
  1458.             pass
  1459.  
  1460.         if self.source == '/var/lib/ubiquity/source':
  1461.             self.umount_source()
  1462.         
  1463.  
  1464.     
  1465.     def chrex(self, *args):
  1466.         '''executes commands on chroot system (provided by *args).'''
  1467.         return misc.ex('chroot', self.target, *args)
  1468.  
  1469.     
  1470.     def copy_debconf(self, package):
  1471.         '''setting debconf database into installed system.'''
  1472.         targetdb = os.path.join(self.target, 'var/cache/debconf/config.dat')
  1473.         misc.ex('debconf-copydb', 'configdb', 'targetdb', '-p', '^%s/' % package, '--config=Name:targetdb', '--config=Driver:File', '--config=Filename:' + targetdb)
  1474.  
  1475.     
  1476.     def set_debconf(self, question, value):
  1477.         dccomm = subprocess.Popen([
  1478.             'log-output',
  1479.             '-t',
  1480.             'ubiquity',
  1481.             '--pass-stdout',
  1482.             'chroot',
  1483.             self.target,
  1484.             'debconf-communicate',
  1485.             '-fnoninteractive',
  1486.             'ubiquity'], stdin = subprocess.PIPE, stdout = subprocess.PIPE, close_fds = True)
  1487.         dc = debconf.Debconf(read = dccomm.stdout, write = dccomm.stdin)
  1488.         dc.set(question, value)
  1489.         dc.fset(question, 'seen', 'true')
  1490.         dccomm.stdin.close()
  1491.         dccomm.wait()
  1492.  
  1493.     
  1494.     def reconfigure(self, package):
  1495.         '''executes a dpkg-reconfigure into installed system to each
  1496.         package which provided by args.'''
  1497.         self.chrex('dpkg-reconfigure', '-fnoninteractive', package)
  1498.  
  1499.  
  1500. if __name__ == '__main__':
  1501.     if not os.path.exists('/var/lib/ubiquity'):
  1502.         os.makedirs('/var/lib/ubiquity')
  1503.     
  1504.     if os.path.exists('/var/lib/ubiquity/install.trace'):
  1505.         os.unlink('/var/lib/ubiquity/install.trace')
  1506.     
  1507.     install = Install()
  1508.     sys.excepthook = install.excepthook
  1509.     install.run()
  1510.     sys.exit(0)
  1511.  
  1512.