home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / boot / i386 / root / usr / share / YaST2 / clients / inst_rpmcopy.ycp < prev    next >
Text File  |  2006-11-29  |  28KB  |  886 lines

  1. /**
  2.  * Module:         inst_rpmcopy.ycp
  3.  *
  4.  * Authors:        Klaus Kaempf <kkaempf@suse.de>
  5.  *            Stefan Hundhammer <sh@suse.de> (slide show)
  6.  *            Arvin Schnell <arvin@suse.de>
  7.  *
  8.  * Purpose:
  9.  * Install all the RPM packages the user has selected.
  10.  * Show installation dialogue. Show progress bars.
  11.  * Request medium change from user.
  12.  *
  13.  * Packages module :
  14.  *            "installed"
  15.  *
  16.  * $Id: inst_rpmcopy.ycp 34305 2006-11-13 12:17:34Z locilka $
  17.  */
  18.  
  19. {
  20.     textdomain "packager";
  21.  
  22.     import "Mode";
  23.     import "Stage";
  24.     import "Installation";
  25.     import "Directory";
  26.     import "Language";
  27.     import "PackageInstallation";
  28.     import "Packages";
  29.     import "SlideShow";
  30.     import "SlideShowCallbacks";
  31.     import "AutoinstSoftware";
  32.     import "Popup";
  33.     import "DirInstall";
  34.     import "Report";
  35.     import "Kernel";
  36.     import "Service";
  37.     import "SourceManager";
  38.     import "Linuxrc";
  39.     import "String";
  40.  
  41.     include "packager/storage_include.ycp";
  42.  
  43.     // variables related to installation source caching
  44.  
  45.     /**
  46.      * File with the information about package cache (between 1st and 2nd
  47.      * installation stage
  48.      */
  49.     string cache_info_path = "/var/lib/YaST2/pkg_cache";
  50.  
  51.     /**
  52.      * Is the disk cache used? (to be stored for 2nd stage)
  53.      */
  54.     boolean store_using_disk_cache = false;
  55.  
  56.     /**
  57.      * Directory containing the cache (to be stored for 2nd stage)
  58.      */
  59.     string store_cache_directory = "";
  60.  
  61.     /**
  62.      * Original source URL (to be stored for 2nd stage)
  63.      */
  64.     string store_original_source_url = "";
  65.  
  66.     /**
  67.      * Cached source ID (during second stage)
  68.      */
  69.     integer cached_source_id = -1;
  70.  
  71.     /**
  72.      * Symlink in the target system (during the first stage)
  73.      */
  74.     string cache_symlink = "";
  75.  
  76.     /**
  77.      * result of Pkg::PkgMediaSizes() from actual install
  78.      */
  79.     list <list <integer> > media_sizes = Pkg::PkgMediaSizes();
  80.  
  81.     /**
  82.      * 'datadir' of cached source (usually 'suse', where packages reside
  83.      */
  84.     string cached_source_datadir = "suse";
  85.  
  86.     // functions related to installation source caching
  87.  
  88.     /**
  89.      * Removes all already installed patches and selections.
  90.      * See bugzilla #210552 for more information.
  91.      */
  92.     void RemoveObsoleteResolvables () {
  93.         y2milestone ("--------- removing obsolete patches and selections ---------");
  94.  
  95.         // this removes only information about selections and applied patches
  96.     // it doesn't remove any package
  97.         y2milestone ("Removing all information about selections and patches in %1", Installation::destdir);
  98.         Pkg::TargetStoreRemove (Installation::destdir, `selection);
  99.     Pkg::TargetStoreRemove (Installation::destdir, `patch);
  100.  
  101.         y2milestone ("--------- removing obsolete patches and selections ---------");
  102.     }
  103.  
  104.     /**
  105.      * Get the source ID of the first source to be cached
  106.      * @return integer cached source ID
  107.      */
  108.     integer CachedSourceId ()
  109.     {
  110.     integer cached_id = -1;
  111.     foreach (integer id, Packages::theSources,
  112.     {
  113.         map<string,string> product_data = (map<string,string>)Pkg::SourceProduct (id);
  114.         y2milestone ("Id %1: SourceProduct %2", id, product_data);
  115.         // FIXME: find()
  116.         if (find (product_data["flags"]:"", "cache") >= 0)
  117.         {
  118.         cached_id = id;
  119.         break;
  120.         }
  121.     });
  122.     y2milestone ("Detected cached source ID: %1", cached_id);
  123.  
  124.     if (cached_id >= 0)
  125.     {
  126.         y2milestone ("SourceGeneralData %1", Pkg::SourceGeneralData(cached_id));
  127.         y2milestone ("SourceMediaData %1", Pkg::SourceMediaData(cached_id));
  128.         y2milestone ("SourceProductData %1", Pkg::SourceProductData(cached_id));
  129.         map<string, any> product_data = Pkg::SourceProductData (cached_id);
  130.         cached_source_datadir = product_data["datadir"]:"suse";
  131.     }
  132.     return cached_id;
  133.     }
  134.  
  135.     /**
  136.      * Store information about the disk cache to the target system
  137.      */
  138.     void StoreDiskCacheSettings ()
  139.     {
  140.     if (! store_using_disk_cache)
  141.     {
  142.         return;
  143.     }
  144.     map settings = $[
  145.         "using_disk_cache" : store_using_disk_cache,
  146.         "original_source_url" : store_original_source_url,
  147.         "cache_directory" : store_cache_directory,
  148.     ];
  149.     y2milestone ("Storing disk cache settings: %1", settings);
  150.     SCR::Write (.target.ycp,
  151.         Installation::destdir + cache_info_path,
  152.         settings);
  153.  
  154.     // remove the symlink created in the target system - not needed any more
  155.     map ta_out = (map)SCR::Execute (.target.bash_output,
  156.       sformat ("/bin/rm -rf %1", cache_symlink));
  157.     }
  158.  
  159.     /**
  160.      * Restore information about the disk cache at the start of the second
  161.      * stage, update the symlink and source location
  162.      */
  163.     void RestoreDiskCacheSettings ()
  164.     {
  165.     map settings = (map)SCR::Read (.target.ycp, [cache_info_path, $[]]);
  166.     if (settings == nil)
  167.     {
  168.         settings = $[];
  169.     }
  170.     y2milestone ("Restored disk cache settings: %1", settings);
  171.     store_using_disk_cache = settings["using_disk_cache"]:false;
  172.     store_original_source_url = settings["original_source_url"]:"";
  173.     store_cache_directory = settings["cache_directory"]:"";
  174.  
  175.     if (! store_using_disk_cache)
  176.     {
  177.         return;
  178.     }
  179.  
  180.     cached_source_id = CachedSourceId ();
  181.  
  182.     Pkg::SourceSetEnabled (cached_source_id, false);
  183.     if (! Pkg::SourceChangeUrl (cached_source_id, store_cache_directory + "/CD1"))
  184.     {
  185.         // error report
  186.         Report::Error (_("Error occurred while switching the service pack catalog."));
  187.     }
  188.     Pkg::SourceSetEnabled (cached_source_id, true);
  189.     }
  190.  
  191.     /**
  192.      * Clean the disk cache up
  193.      */
  194.     void CleanupDiskCache ()
  195.     {
  196.     if (! store_using_disk_cache)
  197.     {
  198.         return;
  199.     }
  200.  
  201.     // 6. Call Pkg::SourceChangeUrl (cached_source_id, source_url) afterwards
  202.  
  203.     Pkg::SourceSetEnabled (cached_source_id, false);
  204.     if (! Pkg::SourceChangeUrl (cached_source_id, store_original_source_url))
  205.     {
  206.         // error report
  207.         Report::Error (_("Error occurred while switching the cached 
  208. source back to CD."));
  209.     }
  210.     Pkg::SourceSetEnabled (cached_source_id, true);
  211.  
  212.     // 7. rm -rf Installation::destdir+"/{var?}/tmp"
  213.     // FIXME: remove _all_ copied CDs
  214.  
  215.     y2milestone ("Deleting cache at %1 and %2", store_cache_directory, cache_info_path);
  216.  
  217.     map ta_out = (map)SCR::Execute (.target.bash_output,
  218.       sformat ("/bin/rm -rf %1; rm -rf %2", store_cache_directory, cache_info_path));
  219.     // TODO error checking - or simply be quiet, it is de-facto no problem
  220.     // for the installation
  221.     }
  222.  
  223.     /**
  224.      * Get the TMP directory to use for packages cache
  225.      * @return string the directory to use
  226.      */
  227.     string GetPkgCacheDirectory ()
  228.     {
  229.  
  230.     //---------
  231.     // find out space on target
  232.  
  233.     map spaces = Pkg::TargetGetDU ();
  234.     list mp_info = spaces["/tmp"]:spaces["/tmp/"]:spaces["/"]:[];
  235.     integer total = mp_info[0]:0;
  236.     integer current = mp_info[1]:0;
  237.     integer future = mp_info[2]:0;
  238.     if (future < current)
  239.     {
  240.         future = current;
  241.     }
  242.     integer tmp_space = total - future;
  243.     if (tmp_space < 0 || mp_info[3]:false)
  244.     {
  245.         tmp_space = 0;
  246.     }
  247.  
  248.     mp_info = spaces["/var/tmp"]:spaces["/var/tmp/"]:spaces["/var"]:spaces["/var/"]:spaces["/"]:[];
  249.     total = mp_info[0]:0;
  250.     current = mp_info[1]:0;
  251.     future = mp_info[2]:0;
  252.     if (future < current)
  253.     {
  254.         future = current;
  255.     }
  256.     integer var_tmp_space = total - future;
  257.     if (var_tmp_space < 0 || mp_info[3]:false)
  258.     {
  259.         var_tmp_space = 0;
  260.     }
  261.  
  262.     //-------
  263.     // /tmp or /var/tmp ?
  264.  
  265.     string cache_dir = tmp_space > var_tmp_space
  266.         ? "/tmp"
  267.         : "/var/tmp";
  268.     integer free_space = tmp_space > var_tmp_space
  269.         ? tmp_space
  270.         : var_tmp_space;
  271.  
  272.     //---------
  273.     // find out needed space for cache
  274.  
  275.     media_sizes = Pkg::PkgMediaSizes();         // fill global media_sizes
  276.     y2milestone ("Media sizes %1", media_sizes);
  277.  
  278.     list<integer> cached_sizes = media_sizes[0]:[];     // assumes source ranking == install ranking
  279.  
  280.     integer needed_space = 0;
  281.     foreach (integer sp_size, cached_sizes,
  282.     {
  283.         needed_space = needed_space + sp_size;
  284.     });
  285.     y2milestone ("Needed space %1 bytes", needed_space);
  286.  
  287.     if (needed_space > free_space)
  288.     {
  289.         y2warning ("Not enough disk space for caching source data");
  290.         return nil;
  291.     }
  292.  
  293.     map ta_out = (map)SCR::Execute (.target.bash_output,
  294.       sformat ("mkdir -p '%1'", String::Quote (Installation::destdir + cache_dir)));
  295.     y2milestone ("Created cached dir '%1': %2", Installation::destdir+cache_dir, ta_out);
  296.     if (ta_out["exit"]:0 != 0)
  297.     {
  298.         Report::Error (sformat (
  299.         // error report
  300.         _("Error occurred while creating directory %1:\n%2"),
  301.         Installation::destdir + cache_dir,
  302.         ta_out["stderr"]:""));
  303.         return nil;
  304.     }
  305.  
  306.     string tmp_dir = cache_dir;
  307.     ta_out = (map)SCR::Execute (.target.bash_output,
  308.       sformat ("mktemp -d -p '%1'", String::Quote (Installation::destdir + cache_dir)));
  309.     y2milestone ("Created temp dir %1: %2", Installation::destdir+cache_dir, ta_out);
  310.     if (ta_out["exit"]:0 != 0)
  311.     {
  312.         Report::Error (sformat (
  313.         // error report
  314.         _("Error occurred while getting temporary directory.\n%1"),
  315.         ta_out["stderr"]:""));
  316.         return nil;
  317.     }
  318.     cache_dir = ta_out["stdout"]:"";
  319.     cache_dir = splitstring (cache_dir, "\n")[0]:cache_dir;
  320.     y2milestone ("Cache dir: %1", cache_dir);
  321.  
  322.     ta_out = (map)SCR::Execute (.target.bash_output,
  323.         // first line is in target system
  324.         // the second one in installation system
  325.          sformat ("rm -rf '%3%1/%4'; ln -s '%3%2' '%3%1/%4';
  326.               rm -rf '%1/%4'; ln -s '%3%2' '%1/%4';",
  327.             tmp_dir,
  328.             substring (cache_dir, size (Installation::destdir)),
  329.             String::Quote (Installation::destdir), cached_source_datadir));
  330.     y2milestone ("rm -rf '%3%1/%4'; ln -s '%3%2' '%3%1/%4';
  331.             rm -rf '%1/%4'; ln -s '%3%2' '%1/%4';",
  332.             tmp_dir,
  333.             substring (cache_dir, size (Installation::destdir)),
  334.             String::Quote (Installation::destdir), cached_source_datadir);
  335.     y2milestone ("Result %1", ta_out);
  336.     if (ta_out["exit"]:0 != 0)
  337.     {
  338.         Report::Error (sformat (
  339.         // error report
  340.         _("Error occurred while getting temporary directory. %1"),
  341.         ta_out["stderr"]:""));
  342.         return nil;
  343.     }
  344.     // prepare local paths settings for being stored
  345.     store_cache_directory = substring (cache_dir, size (Installation::destdir));
  346.  
  347.     cache_dir = sformat ("%1%2/%3", Installation::destdir, tmp_dir, cached_source_datadir);
  348.     cache_symlink = cache_dir;
  349.  
  350.     y2milestone ("Directory for packages cache: %1", cache_dir);
  351.     return cache_dir;
  352.     }
  353.  
  354.     /**
  355.      * Prepare the disk cache for the cached source
  356.      * @param source_id integer source ID to be cached
  357.      */
  358.     void PrepareSourceCache (integer source_id)
  359.     {
  360.     // steps of the implementation
  361.  
  362.     y2milestone ("PrepareSourceCache (%1)", source_id);
  363.     // 0. Find out which packages (only names) we need
  364.     //    build list media_nr, "<arch>/<package_name>.rpm" for all cached RPMs
  365.  
  366.     list<string> selected_packages = Pkg::GetPackages (`selected, true);
  367.     list<list <string> > cached_packs = [];
  368.     map<string, string> cached_archs = $[];
  369.  
  370.     foreach (string package, selected_packages,
  371.     {
  372.         map<string, any> pkg_props = (map<string, any>)Pkg::PkgProperties (package);
  373.         y2milestone ("Package %1, Properties %2", package, pkg_props);
  374.         if (pkg_props["srcid"]:-1 == source_id)
  375.         {
  376.         integer media_nr = pkg_props["medianr"]:0;
  377.         string fullname = pkg_props["location"]:"";
  378.         string arch = pkg_props["arch"]:"";
  379.         string pkgpath = cached_source_datadir + "/" + arch + "/" + fullname;
  380.  
  381.         cached_archs[arch] = arch;                  // remember all encountered architectures
  382.  
  383.         integer cached_size = size (cached_packs[media_nr]:[]);
  384.         if (cached_size == 0)
  385.         {
  386.             cached_packs[media_nr] = [pkgpath];         // create a list
  387.         }
  388.         else
  389.         {
  390.             cached_packs[media_nr, cached_size] = pkgpath;      // add to existing list
  391.         }
  392.         }
  393.     });
  394.  
  395.     // 1. check where space is available
  396.     // Installation::destdir+"/tmp"
  397.     // or Installation::destdir+"/var/tmp" ?
  398.     // choose the one where more space is available
  399.  
  400.     string cache_dir = GetPkgCacheDirectory ();
  401.     if (cache_dir == nil)
  402.     {
  403.         y2error ("Could not get the directory for the cache");
  404.         return;
  405.     }
  406.  
  407.     // 2. Use PackageCallbacks::MediaChange() to ask for cached cd
  408.     // (problem: where to get all the strings MediaChange() needs)
  409.     // Asking Pkg::SourceProvideDir also gives the directory
  410.     // with the data and should ask for the CD
  411.  
  412.     // 3a. Find out which source CDs we really need
  413.  
  414.     list <integer> cached_sizes = media_sizes[0]:[0];       // look at install size of cached source
  415.     integer media_number = 1;
  416.  
  417.     y2milestone ("cached_sizes %1", cached_sizes);
  418.  
  419.     // loop over all medias in the cached size list and copy those which are needed
  420.  
  421.     foreach (integer current_size, cached_sizes,
  422.     {
  423.         y2milestone ("Need %1 bytes from media #%2", current_size, media_number);
  424.  
  425.         if (current_size > 0)
  426.         {
  427.         y2milestone ("Packages %1", cached_packs[media_number]:[]);
  428.  
  429.         string update_dir = Pkg::SourceProvideDir (source_id, media_number, "/");
  430.         if (update_dir == nil)
  431.         {
  432.             y2error ("Pkg::SourceProvideDir (%1, %2, %3) failed", source_id, media_number, "/");
  433.             // error report
  434.             Report::Error (_("Error occurred while getting the directory with updated packages"));
  435.             return;
  436.         }
  437.  
  438.         // 3. Copy <cached_source_datadir>/<arch>/<package> from cached source to Installation::destdir+"/{var?}/tmp"
  439.  
  440.         // translators: this is an information popup, %1 is a number
  441.         UI::OpenDialog (`Label (sformat (_("Copying files from CD %1 to disk..."), media_number)));
  442.  
  443.         y2milestone ("Creating directory %1", sformat ("/bin/mkdir -p %1/CD%2", cache_dir, media_number));
  444.  
  445.         map ta_out = (map)SCR::Execute (.target.bash_output,
  446.           sformat ("/bin/mkdir -p %1/CD%2", cache_dir, media_number));
  447.         y2milestone ("mkdir returned %1, copying media files", ta_out);
  448.         ta_out = (map)SCR::Execute (.target.bash_output,
  449.           sformat ("/bin/cp -a %1/media* %2/CD%3", update_dir, cache_dir, media_number));
  450.         y2milestone ("media copy returned %1", ta_out);
  451.  
  452.         if (ta_out["exit"]:0 != 0)
  453.         {
  454.             UI::CloseDialog ();
  455.             y2error ("copying media files failed");
  456.             // error report
  457.             Report::Error (sformat (_("Error occurred while copying packages
  458. from the source CD to the disk")));
  459.             return;
  460.         }
  461.  
  462.         // create needed arch-subdirs
  463.  
  464.         foreach (string arch, string dummy, cached_archs, {
  465.             y2milestone ("Creating %1", sformat ("%1/CD%2/%3/%4", cache_dir, media_number, cached_source_datadir, arch));
  466.             SCR::Execute (.target.bash_output, sformat ("/bin/mkdir -p %1/CD%2/%3/%4", cache_dir, media_number, cached_source_datadir, arch));
  467.         });
  468.  
  469.         // copy needed packages
  470.  
  471.         foreach (string pkgpath, cached_packs[media_number]:[],
  472.         {
  473.             y2milestone ("Copy %1/%2 to %3/CD%4/%2", update_dir, pkgpath, cache_dir, media_number);
  474.             ta_out = (map)SCR::Execute (.target.bash_output,
  475.               sformat ("/bin/cp %1/%2 %3/CD%4/%2", update_dir, pkgpath, cache_dir, media_number));
  476.  
  477.             if (ta_out["exit"]:0 != 0)
  478.             {
  479.             UI::CloseDialog ();
  480.             // error report
  481.             Report::Error (sformat (_("Error occurred while copying packages
  482. from the source CD to the disk cache")));
  483.             return;
  484.             }
  485.         });
  486.  
  487.         UI::CloseDialog ();
  488.  
  489.         }  // current_size > 0
  490.  
  491.         media_number = media_number + 1;
  492.  
  493.     }); // loop over all cached source media
  494.  
  495.     // 4. Create URL as cached_url = "dir://"+Installation::destdir+"/{var?}/tmp"
  496.  
  497.     string cached_url = "dir:/" + cache_dir + "/CD1";
  498.     y2milestone ("Cache URL: %1", cached_url);
  499.  
  500.     // 5. Call Pkg::SourceChangeUrl (source_id, cached_url);
  501.     // keep your fingers crossed
  502.  
  503.     Pkg::SourceSetEnabled (source_id, false);
  504.     boolean scu = Pkg::SourceChangeUrl (source_id, cached_url);
  505.     Pkg::SourceSetEnabled (source_id, true);
  506.  
  507.     if (! scu)
  508.     {
  509.         // error report
  510.         Report::Error (_("Switching to disk cache failed."));
  511.         return;
  512.     }
  513.  
  514.     y2milestone ("Switch to disk cache successfully finished");
  515.  
  516.     store_using_disk_cache = true;
  517.  
  518.     }
  519.  
  520.     // ------------------------------------------------------------------------------------------------------
  521.     // end of installation source caching functions
  522.     // ------------------------------------------------------------------------------------------------------
  523.  
  524.     // ------------------------------------------------------------------------------------------------------
  525.     // begin of commit installation functions
  526.     // ------------------------------------------------------------------------------------------------------
  527.  
  528.     void InstallRemainingAndBinarySource () {
  529.     // second stage of package installation, re-read list of remaining binary and source
  530.     // packages
  531.  
  532.     list<map<string,any> > remaining = (list<map<string,any> >) SCR::Read (.target.ycp, ["/var/lib/YaST2/remaining", []]);
  533.     if (remaining == nil)
  534.         remaining = [];
  535.  
  536.     list<string> srcremaining = (list<string>) SCR::Read (.target.ycp, ["/var/lib/YaST2/srcremaining", []]);
  537.     if (srcremaining == nil)
  538.         srcremaining = [];
  539.  
  540.     string backupPath = (string) SCR::Read(.target.string, [Installation::destdir + "/var/lib/YaST2/backup_path", ""]);
  541.     if ( backupPath != nil && backupPath != "")
  542.     {
  543.         y2milestone("create package backups in %1",backupPath);
  544.         Pkg::CreateBackups (true);
  545.         Pkg::SetBackupPath (backupPath);
  546.     }
  547.  
  548.     integer failed_packages = 0;
  549.     y2milestone ("%1 resolvables remaining", size (remaining));
  550.     foreach (map<string,any> res, remaining, ``{
  551.         string name = res["name"]:"";
  552.         symbol kind = res["kind"]:`package;
  553.         string arch = res["arch"]:"";
  554.         string vers = res["version"]:"";
  555.         if (! Pkg::ResolvableInstallArchVersion (name, kind, arch, vers))
  556.         failed_packages = failed_packages + 1;
  557.     });
  558.  
  559.     y2milestone ("%1 source packages remaining", size (srcremaining));
  560.     foreach (string pkg, srcremaining, ``{
  561.         if (! Pkg::PkgSrcInstall (pkg))
  562.         failed_packages = failed_packages + 1;
  563.     });
  564.     if (failed_packages > 0)
  565.     {
  566.         // error report, %1 is number
  567.         Report::Error (sformat(_("Failed to select %1 packages for installation."), failed_packages));
  568.     }
  569.     }
  570.  
  571.     void InstInitAndInitialSourceCaching () {
  572.     map spaces = Pkg::TargetGetDU ();
  573.     list root_info = spaces["/tmp"]:spaces["/tmp/"]:spaces["/"]:[];
  574.     integer total = root_info[0]:0;
  575.     integer current = root_info[1]:0;
  576.     integer future = root_info[2]:0;
  577.     if (future < current)
  578.         future = current;
  579.     integer tmp_space = total - future;
  580.     // no temp space left or read-only
  581.     if (tmp_space < 0 || root_info[3]:1 == 1)
  582.         tmp_space = 0;
  583.  
  584.     list var_info = spaces["/var/tmp"]:spaces["/var/tmp/"]:spaces["/var"]:spaces["/var/"]:spaces["/"]:[];
  585.     total = var_info[0]:0;
  586.     current = var_info[1]:0;
  587.     future = var_info[2]:0;
  588.     if (future < current)
  589.         future = current;
  590.     integer var_tmp_space = total - future;
  591.     // no temp space left or read-only
  592.     if (var_tmp_space < 0 || var_info[3]:1 == 1)
  593.         var_tmp_space = 0;
  594.  
  595.     //-------
  596.     // /tmp or /var/tmp ?
  597.  
  598.     string download_dir = tmp_space > var_tmp_space
  599.         ? "/tmp"
  600.         : "/var/tmp";
  601.     download_dir = Installation::destdir + download_dir;
  602.     integer space = tmp_space > var_tmp_space
  603.         ? tmp_space
  604.         : var_tmp_space;
  605.     if (true) // TODO check the size of the largest package on CD1
  606.     {
  607.         SCR::Execute (.target.bash, sformat ("test -d %1 || mkdir %1", download_dir));
  608.         Pkg::SourceMoveDownloadArea (download_dir);
  609.     }
  610.  
  611.     // FIXME: find()
  612.         if (find (Kernel::GetCmdLine (), "yastnocache") != -1)
  613.         {
  614.             y2milestone ("'yastnocache' found, disabling source cache");
  615.             cached_source_id = -1;
  616.         }
  617.         else
  618.         {
  619.             cached_source_id = CachedSourceId ();
  620.         }
  621.  
  622.         if (cached_source_id >= 0)
  623.         {
  624.             y2milestone ("Installing with cached source, checking inst media");
  625.  
  626.             map<string,any> source_data = (map<string,any>)Pkg::SourceGeneralData (cached_source_id);
  627.             y2milestone ("Cached source #%1: %2", cached_source_id, source_data);
  628.  
  629.             string source_url = "";
  630.             if (source_data != nil) source_url = source_data["url"]:"";
  631.  
  632.             if (substring (source_url, 0, 4) == "cd:/"
  633.         || substring (source_url, 0, 5) == "dvd:/")
  634.             {
  635.                 y2milestone ("Installing from DVD/CDs, trying to set up cache");
  636.                 store_original_source_url = source_url;
  637.                 PrepareSourceCache (cached_source_id);
  638.             }
  639.             else
  640.             {
  641.                 y2error ("Cannot get the URL of the cached source, not caching");
  642.             }
  643.         }
  644.     }
  645.  
  646.     void AutoinstPostPackages () {
  647.     import "AutoinstSoftware";
  648.  
  649.     // post packages from autoinstall
  650.     map <string, any> res = Pkg::DoProvide (AutoinstSoftware::post_packages);
  651.     if (size (res) > 0)
  652.     {
  653.         foreach (string s, any a, res, ``{
  654.         y2warning ("Pkg::DoProvide failed for %1: %2", s, a);
  655.         });
  656.     }
  657.  
  658.     Pkg::PkgSolve (false);
  659.     }
  660.  
  661.     symbol InstallPackagesFromMedia (integer current_cd_no, integer maxnumbercds) {
  662.       symbol result = `next;
  663.  
  664.       y2milestone("Installing packages from media %1 -> %2", current_cd_no, maxnumbercds);
  665.  
  666.       // 1->1 for default fist stage installation
  667.       // 0->0 for default second stage (or other) installation
  668.       while (current_cd_no <= maxnumbercds) {
  669.     boolean go_on = true;
  670.     list<map<string,any> > pkgs = Pkg::ResolvableProperties ("", `package, "");
  671.     pkgs = filter (map<string,any> p, pkgs, {
  672.         return p["status"]:nil == `selected;
  673.     });
  674.     if (size (pkgs) == 0)
  675.     {
  676.         y2milestone ("No package left for installation");
  677.         break;
  678.     }
  679.  
  680.     // returns [ int successful, list failed, list remaining ]
  681.     list commit_result = PackageInstallation::CommitPackages( current_cd_no, 0 );
  682.     if (size (commit_result) == 0)
  683.     {
  684.         return `abort;
  685.     }
  686.  
  687.     integer count = commit_result[0]:0;
  688.     y2milestone ("%1 packages installed", count);
  689.  
  690.     list failed = commit_result[1]:[];
  691.     if (size (failed) > 0)
  692.     {
  693.         y2milestone ("failed: %1", failed);
  694.         list previous_failed = (list) SCR::Read (.target.ycp, [Installation::destdir +
  695.                                    "/var/lib/YaST2/failed_packages", []]);
  696.         if (size (previous_failed) > 0)
  697.         failed = union (previous_failed, failed);
  698.         SCR::Write (.target.ycp, Installation::destdir + "/var/lib/YaST2/failed_packages", failed);
  699.     }
  700.  
  701.     list remaining = commit_result[2]:[];
  702.     if (size (remaining) >= 0)
  703.     {
  704.         y2milestone ("remaining: %1", remaining);
  705.         SCR::Write (.target.ycp, Installation::destdir + "/var/lib/YaST2/remaining", remaining);
  706.     }
  707.     else
  708.     {
  709.         SCR::Execute (.target.remove, Installation::destdir + "/var/lib/YaST2/remaining");
  710.     }
  711.  
  712.     list srcremaining = commit_result[3]:[];
  713.     if (size (srcremaining) >= 0)
  714.     {
  715.         y2milestone ("source remaining: %1", srcremaining);
  716.         SCR::Write (.target.ycp, Installation::destdir + "/var/lib/YaST2/srcremaining", srcremaining);
  717.     }
  718.     else
  719.     {
  720.         SCR::Execute (.target.remove, Installation::destdir + "/var/lib/YaST2/srcremaining");
  721.     }
  722.  
  723.     if (count < 0)                    // aborted by user
  724.     {
  725.         result = `abort;
  726.         break;
  727.     }
  728.  
  729.     // break on first round with Mediums
  730.     if (Stage::initial () && !Mode::test ())
  731.         break;
  732.  
  733.     current_cd_no = current_cd_no + 1;
  734.       }
  735.       return result;
  736.     }
  737.  
  738.     map <string, integer> CountStartingAndMaxMediaNumber () {
  739.     // Bugzilla #170079
  740.     // Default - unrestricted
  741.     map <string, integer> ret = $["maxnumbercds" : 0, "current_cd_no" : 0];
  742.  
  743.     // has the inst-sys been successfuly unmounted?
  744.     string umount_result = Linuxrc::InstallInf ("umount_result");
  745.     string media = Linuxrc::InstallInf ("InstMode");
  746.     y2milestone("umount result: %1, inst source type: %2", umount_result, media);
  747.  
  748.     if (Packages::metadir_used) {
  749.         // all is in ramdisk, we can install all sources now, works in every stage
  750.         ret["current_cd_no"] = 0;
  751.         ret["maxnumbercds"]  = 0;
  752.         y2milestone("StartingAndMaxMediaNumber: MetaDir used %1/%2", ret["current_cd_no"]:nil, ret["maxnumbercds"]:nil);
  753.     } else if (Stage::initial ()) {
  754.         // is CD or DVD medium mounted? (inst-sys)
  755.         if (umount_result != "0" && (media == "cd" || media == "dvd"))
  756.         {
  757.         y2milestone("The installation CD/DVD cannot be changed.");
  758.         // only the first CD will be installed
  759.         ret["current_cd_no"] = 1;
  760.         ret["maxnumbercds"]  = 1;
  761.         }
  762.         // otherwise use the default setting - install all media
  763.         y2milestone("StartingAndMaxMediaNumber: Stage initial %1/%2", ret["current_cd_no"]:nil, ret["maxnumbercds"]:nil);
  764.  
  765.     // Three following cases have the same solution, CDstart = 0, CDfinish = 0
  766.     // ZYPP should solve what it needs and when.
  767.     // Leaving it here as the backward compatibility if someone decides to change it back.
  768.  
  769.     } else if (Mode::autoinst () && Stage::cont () && size( AutoinstSoftware::post_packages ) > 0) {
  770.         // one more compatibility feature to old YaST, post-packages
  771.         // Simply install a list of package after initial installation (only
  772.         // makes sense with nfs installatons)
  773.         ret["current_cd_no"]  = 0; // was 1
  774.         ret["maxnumbercds"]   = 0; // was 10
  775.         y2milestone("StartingAndMaxMediaNumber: Autoinst in cont %1/%2", ret["current_cd_no"]:nil, ret["maxnumbercds"]:nil);
  776.     } else if (Stage::cont ()) {
  777.         // continue with second CD but only in continue mode
  778.         // bug #170079, let zypp solve needed CDs
  779.         ret["current_cd_no"]  = 0;
  780.         ret["maxnumbercds"]   = 0;
  781.         y2milestone("StartingAndMaxMediaNumber: Stage cont %1/%2", ret["current_cd_no"]:nil, ret["maxnumbercds"]:nil);
  782.     } else if (DirInstall::installing_into_dir) {
  783.         // All in one
  784.         ret["current_cd_no"]  = 0; // was 1
  785.         ret["maxnumbercds"]   = 0; // was 10
  786.         y2milestone("StartingAndMaxMediaNumber: Dir install %1/%2", ret["current_cd_no"]:nil, ret["maxnumbercds"]:nil);
  787.     }
  788.  
  789.     return ret;
  790.     }
  791.  
  792.     // ------------------------------------------------------------------------------------------------------
  793.     // end of commit installation functions
  794.     // ------------------------------------------------------------------------------------------------------
  795.  
  796.     // bugzilla #208222
  797.     ReleaseHDDUsedAsInstallationSource();
  798.  
  799.     Pkg::SetLocale (Language::language);
  800.  
  801.     SlideShow::SetLanguage (Language::language);
  802.  
  803.     // start target, create new rpmdb if none is existing
  804.     // FIXME error checking is missing all around here, initialization could actually fail!
  805.     //Pkg::TargetInit (Installation::destdir, true);
  806.     if (Pkg::TargetInitialize (Installation::destdir) != true)
  807.     {
  808.     // continue-cancel popup
  809.         if(Popup::ContinueCancel(_("Initializing the target directory failed")) == false)
  810.         {
  811.             return `abort;
  812.         }
  813.     }
  814.     
  815.     if (Mode::update()) {
  816.     // Removes all already installed patches and selections.
  817.     // See bugzilla #210552 for more information.
  818.     RemoveObsoleteResolvables();
  819.     } 
  820.  
  821.     if (Stage::cont ())
  822.     {
  823.     // initialize the package agent in continue mode
  824.     Packages::Init( true );
  825.     RestoreDiskCacheSettings ();
  826.     }
  827.  
  828.     SlideShow::OpenSlideShowDialog ();
  829.  
  830.     Pkg::TargetLogfile (Installation::destdir + Directory::logdir + "/y2logRPM");
  831.  
  832.  
  833.     if  (Mode::autoinst () && Stage::cont ()) {
  834.     AutoinstPostPackages();
  835.     }
  836.  
  837.     // initial mode, move download area, check for source caching
  838.     if (Stage::initial ()) {
  839.     InstInitAndInitialSourceCaching();
  840.     // continue mode, check for remaining packages
  841.     } else {
  842.     InstallRemainingAndBinarySource();
  843.     }
  844.  
  845.     // Install the software from Medium1 to Mediummax, but not the already
  846.     // installed base packages.
  847.     // This part is also used for installation in running system (Stage::cont ())
  848.  
  849.     map <string, integer> cdnumbers = CountStartingAndMaxMediaNumber();
  850.     integer maxnumbercds  = cdnumbers["maxnumbercds"]:10;
  851.     integer current_cd_no = cdnumbers["current_cd_no"]:1;
  852.  
  853.     // install packages from CD current_cd_no to CD maxnumbercds
  854.     symbol result = InstallPackagesFromMedia (current_cd_no, maxnumbercds);
  855.  
  856.     // sync package manager FIXME
  857.     if (result != `abort && ! Stage::initial ())
  858.     {
  859.     y2milestone ("Calling PkgCommit (%1)", 9999);
  860.     Pkg::PkgCommit (9999);
  861.     }
  862.  
  863.     // reinitialize the package manager from the target,
  864.     // refresh installed/uninstalled status (#201121)
  865.     Pkg::TargetFinish();
  866.     Pkg::TargetInitialize(Installation::destdir);
  867.     Pkg::TargetLoad();
  868.  
  869.     SlideShow::CloseSlideShowDialog();
  870.  
  871.     if (result != `abort)
  872.     {
  873.     if (Stage::initial ())
  874.     {
  875.         StoreDiskCacheSettings ();
  876.     }
  877.     else if (Stage::cont ())
  878.     {
  879.         SourceManager::SyncYaSTInstSourceWithZMD (); // #156030
  880.         CleanupDiskCache ();
  881.     }
  882.     }
  883.     
  884.     return result;
  885. }
  886.