home *** CD-ROM | disk | FTP | other *** search
- /**
- * Module: inst_source.ycp
- *
- * Author: Cornelius Schumacher <cschum@suse.de>
- *
- * Purpose:
- * Adding, removing and prioritizing of installation sources for packagemanager.
- *
- */
-
- {
- textdomain "packager";
-
- import "Confirm";
- import "Mode";
- import "Installation";
- import "PackageCallbacksInit";
- import "PackageLock";
- import "PackageSystem";
- import "Report";
- import "SLP";
- import "Stage";
- // SourceManager overlaps quite a bit with inst_source,
- // so far we only use it for ZMD sync, TODO refactor better
- import "SourceManager";
- import "SuSEFirewall";
- import "Wizard";
-
- import "Label";
- import "Popup";
- import "AddOnProduct";
- import "Sequencer";
-
- // Do not sync the changes to ZENworks even if rug is present
- // This is handy for repairing an already out-of-sync situation
- boolean have_rug = (integer)SCR::Read (.target.size, "/usr/bin/rug") >= 0;
- boolean norug = !have_rug || WFM::Args(0) == "norug";
-
- // constant Plaindir
- string plaindir_type = "Plaindir";
-
- Wizard::CreateDialog();
- Wizard::SetDesktopIcon("sw_source");
- // dialog caption
- Wizard::SetContents(_("Initializing..."), `Empty (), "", false, true);
-
- // check whether running as root
- if (! Confirm::MustBeRoot () || ! PackageLock::Check ())
- {
- UI::CloseDialog ();
- return (any)`abort;
- }
-
- PackageCallbacksInit::InitPackageCallbacks ();
-
- // constructor of Product is needed in order to initialize the product
- // macro. Takes a lot of time because whole package manager target
- // is initialized
- import "Product";
-
- include "packager/inst_source_dialogs.ycp";
-
- integer numSources = 0;
-
- list<map<string,any> > sourceStatesIn = [];
- list<map<string,any> > sourceStatesOut = [];
- list<integer> sourcesToDelete = [];
-
- /**
- Create a table item from a map as returned by the InstSrcManager agent.
- @param source The map describing the source as returned form the agent.
- @return An item suitable for addition to a Table.
- */
- define term createItem( integer index, map source ) ``{
- integer id = source[ "SrcId" ]:0;
- map generalData = Pkg::SourceGeneralData( id );
- map productData = Pkg::SourceProductData( id );
- y2milestone("generalData: %1", generalData);
- y2milestone("productData: %1", productData);
- term item = `item(
- `id( index ),
- // corresponds to the "Enable/Disable" button
- source[ "enabled" ]:true ? _("On") : _("Off"),
- source["autorefresh"]:true ? _("On") : _("Off"),
- // translators: unknown name for a given source
- productData[ "label" ]:generalData[ "type" ]: _("unknown"),
- generalData[ "url" ]:""
- );
- return item;
- }
-
- /**
- * Fill sources table with entries from the InstSrcManager agent.
- */
- define void fillTable() ``{
- y2milestone ("Filling source table");
- list items = [];
-
- numSources = size( sourceStatesOut );
-
- integer i = 0;
- while ( i < numSources ) {
- items = add( items, createItem( i, sourceStatesOut[ i ]:$[] ) );
- i = i + 1;
- }
-
- UI::ChangeWidget( `id( `table ), `Items, items );
- }
-
- boolean LicenseAccepted (integer id) {
- Wizard::CreateDialog ();
- boolean ret = AddOnProduct::AcceptedLicenseAndInfoFile (id);
- UI::CloseDialog ();
- return ret;
- }
-
- define symbol createSource( string url ) ``{
- y2milestone("createSource: %1", url);
-
- if ( url != "" )
- {
- // for Plaindir source we have to use SourceCreateType() binding
- boolean plaindir = false;
- map parsed = URL::Parse(url);
- string scheme = parsed["scheme"]:"";
-
- if (scheme == "pkg")
- {
- parsed["scheme"] = "dir";
- url = URL::Build(parsed);
- plaindir = true;
- }
-
- // check if SMB/CIFS share can be mounted
- if (scheme == "smb" && SCR::Read(.target.size, "/sbin/mount.cifs") < 0)
- {
- y2milestone("SMB/CIFS share cannot be mounted, installing missing 'cifs-mount' package...");
- // install cifs-mount package
- PackageSystem::CheckAndInstallPackages(["cifs-mount"]);
- }
-
- list<integer> newSources = (plaindir) ?
- [ Pkg::SourceCreateType(url, "", plaindir_type) ] :
- Pkg::SourceScan( url, "" );
-
- if ( size( newSources ) == 0 )
- {
- // message part 1
- string _msg1 = sformat( _("Unable to create installation source
- from URL '%1'."), url );
- /* FIXME Pkg::LastErrorId always returns 'ok'
- string err = Pkg::LastErrorId();
- if ( err != "ok" ) {
- if ( err == "instsrc_duplicate" )
- // message part 2 alt. 1
- _msg2 = _("A catalog for this product already exists.");
- else
- }
- */
- // message part 2 alt. 2 followed by description
- string _msg2 = _("Details:") + "\n" + Pkg::LastError() + "\n" +
- // message part 3
- _("Try again?");
-
- boolean tryagain = Popup::YesNo( _msg1 + "\n" + _msg2 );
- if ( tryagain ) return `again;
- else return `cancel;
- }
- else
- {
- list<integer> prod_sources = filter (integer s, newSources, {
- map src_data = Pkg::SourceGeneralData (s);
- string src_type = src_data["type"]:"";
- return (src_type == "YaST" || src_type == "YUM" || src_type == plaindir_type);
- });
- if (size (prod_sources) == 0)
- {
- if (! Popup::AnyQuestion (
- Popup::NoHeadline (),
- // continue-back popup
- _("There is no product information available at the given location.
- If you expected to address a product, return back and enter
- the correct location.
- To make rpm packages located at the specified location available
- in the packages selection, continue."),
- Label::ContinueButton (),
- Label::BackButton (),
- `focus_yes))
- {
- return `again;
- }
- }
- foreach( integer id, newSources, ``{
- if (! LicenseAccepted (id))
- {
- Pkg::SourceDelete (id);
- }
- else
- {
- map src_data = Pkg::SourceGeneralData (id);
- boolean auto_refresh = src_data["autorefresh"]:false;
- map<string, any> sourceState = $[ "SrcId": id, "enabled": true, "autorefresh" : auto_refresh ];
- sourceStatesOut = add( sourceStatesOut, sourceState );
- }
- } );
- return `ok;
- }
- }
- }
-
- /**
- * Find which sources have to be added or deleted to ZENworks.
- * #182992: formerly we did not consider the enabled attribute.
- * But ZENworks cannot completely disable a source (unsubscribing a
- * catalog merely decreases its priority) so we consider a disabled source
- * like a deleted one.
- * @param statesOld sourceStates{In or Out}
- * @param statesNew sourceStates{In or Out}
- * @return the list of SrcId's that are enabled in statesNew
- * but are not enabled in statesOld
- */
- list<integer> newSources (list<map<string,any> > statesOld,
- list<map<string,any> > statesNew) {
- y2milestone ("From %1 To %2", statesOld, statesNew);
- list<integer> ret = [];
- map<integer, boolean> seen = listmap (
- map<string, any> src, statesOld,
- ``( $[(src["SrcId"]:-1) : (src["enabled"]:true) ] ));
- foreach (map<string, any> src, statesNew, {
- integer newid = src["SrcId"]:-1;
- boolean newena = src["enabled"]:true;
- if (newena && ! seen[newid]:false)
- ret = add (ret, newid);
- });
- y2milestone ("Difference %1", ret);
- return ret;
- }
-
- define void deleteSource( integer index ) ``{
- integer srcid = sourceStatesOut[index, "SrcId"]:-1;
-
- if( srcid != -1)
- sourcesToDelete = add( sourcesToDelete, srcid );
-
- sourceStatesOut = remove( sourceStatesOut, index );
- }
-
- boolean Write() {
- boolean success = Pkg::SourceEditSet( sourceStatesOut );
-
- // we must sync before the sources are deleted from zypp
- // otherwise we will not get their details
- list<integer> added = newSources (sourceStatesIn, sourceStatesOut);
- list<integer> deleted = newSources (sourceStatesOut, sourceStatesIn);
- boolean have_rug = !norug && (integer)SCR::Read (.target.size, "/usr/bin/rug") >= 0;
- boolean any_changed = added != [] || deleted != []; // #217697
- if (success && have_rug && any_changed) {
- UI::OpenDialog (
- `VBox (
- `Label (SourceManager::SyncLabel ()),
- `PushButton (`id (`abort), Label::AbortButton ())
- ));
- boolean syncok = SourceManager::SyncAddedAndDeleted (added, deleted);
- UI::CloseDialog ();
- if (!syncok)
- {
- // yes/no popup
- if (!Popup::YesNo (_("Source synchronization with ZMD failed.
- Save changes anyway?")))
- success = false;
-
- }
- }
- else {
- y2milestone ("No rug, not syncing");
- }
-
- foreach( integer id, sourcesToDelete, ``{
- success = success && Pkg::SourceDelete(id);
- });
-
- // store in the persistent libzypp storage
- success = success && Pkg::SourceSaveAll(); // #176013
-
- return success;
- }
-
-
- symbol SummaryDialog () {
- y2milestone ("Running Summary dialog");
- list items = [];
-
- // pusg button
- string replaceButtonLabel = _("&Replace...");
- // pusg button
- string refreshButtonLabel = _("Re&fresh Now...");
- // pusg button
- string enableButtonLabel = _("Enab&le or Disable");
- // push button
- string refreshOnOffButtonLabel = _("Refre&sh On or Off");
-
- term contents =
- `VBox(
- `HBox(
- `Table( `id( `table ),/* `opt( `keepSorting ),*/
- // table header
- `header( _("Status"),
- // table header
- _("Refresh"),
- // table header
- _("Name"),
- // table header
- _("URL") ),
- items ),
- `HSpacing()
- ),
- // TODO Help
- `Left (`CheckBox (`id (`zmdsync),
- // Checkbox label
- _("Synchronize Changes with &ZENworks"),
- !norug)),
- `HBox(
- `PushButton (`id (`add), `opt(`key_F3),
- Label::AddButton ()),
- `PushButton(`id(`replace), `opt(`key_F4),
- Label::EditButton ()),
- `PushButton (`id(`delete), `opt(`key_F5),
- Label::DeleteButton ()),
- `HStretch (),
- // menu button label
- `MenuButton (`opt(`key_F6), _("Source Settings"), [
- `item(`id(`enable), enableButtonLabel),
- `item(`id(`refresh_on_off), refreshOnOffButtonLabel),
- `item(`id(`refresh), refreshButtonLabel )
- ])
- ),
- `VSpacing( 0.5 )
- );
-
- // dialog caption
- string title = _("Configured Software Catalogs");
- // string title = _("Media Containing the Software Catalog");
-
- // help
- string help_text = _("<p>
- In this dialog, manage configured software catalogs.</p>");
-
- help_text = help_text + _("<p>
- <b>Adding a New Catalog</b><br>
- To add a new catalog, use <b>Add</b> and specify the software catalog.
- </p>");
-
- // help, continued
- help_text = help_text + _("<p>
- To install packages from <b>CD</b>,
- have the &product; CD set or the DVD available.
- </p>
- ");
-
- // help, continued
- help_text = help_text + _("<p>
- The &product; CDs can be copied to the <b>hard disk</b>.
- Then use that as the installation source.
- Insert the path name where the first
- CD is located, for example, /data1/<b>CD1</b>.
- Only the base path is required if all CDs are copied
- into one directory.
- </p>
- ");
-
- // help, continued
- help_text = help_text + _("<p>
- <b>Network</b> installation requires a working network connection.
- Configure YaST2's \"Network Devices\" module first,
- if required. Specify the directory where the packages from
- the first CD are located, such as /data1/CD1.
- Only the base path is
- required if packages are not divided, for example, /usr/full-i386.
- The directory must be listed in the file <i>/etc/exports</i>
- on the NFS server.
- </p>
- ");
-
- // help, continued
- help_text = help_text + _("<p>
- <b>Modifying a Catalog</b>
- To change a catalog media, use <b>Edit</b>. To remove a catalog, use
- <b>Delete</b>. To enable or disable the catalog, set refreshing on the
- initialization time on or off, or refresh it immediatelly, use
- <b>Source Settings</b>.");
-
- // help, continued
- help_text = help_text + _("<p>
- <b>Synchronize Changes with ZENworks</b> will call <tt>rug</tt>
- to perform the changes also in that package management system.</p>");
-
- Wizard::SetNextButton(`next, Label::FinishButton() );
- Wizard::SetContents(title, contents, help_text, false, true);
- Wizard::HideBackButton();
- UI::ChangeWidget (`id (`zmdsync), `Enabled, have_rug);
-
- fillTable();
-
- symbol input = nil;
-
- integer current = -1;
-
- string url = "";
-
- boolean exit = false;
-
- repeat {
-
- if ( current >= 0 ) {
- UI::ChangeWidget( `id( `table ), `CurrentItem, current );
- }
-
- input = (symbol)Wizard::UserInput();
- y2debug( "Input: %1", input );
-
- symbol createResult = `again;
-
- if (input == `add)
- {
- return `add;
- }
- if ( input == `next )
- {
- norug = ! (boolean) UI::QueryWidget (`id (`zmdsync), `Value);
- // store the new state
- boolean success = Write();
- if ( !success ) {
- // popup message part 1
- string _msg1 = _("Unable to save changes to installation source
- configuration.");
- string details = Pkg::LastError();
- // popup message part 2 followed by other info
- string _msg2 = details != "" ? (_("Details:") + "\n" + details)
- : "";
- // popup message part 3
- _msg2 = _msg2 + "\n" + _("Try again?");
-
- boolean tryagain = Popup::YesNo( _msg1 + "\n" + _msg2 );
- if ( !tryagain ) exit = true;
- } else {
- exit = true;
- }
- }
- // Wizard::UserInput returns `back instead of `cancel when window is closed by WM
- else if (input == `abort || input == `back)
- {
- // popup headline
- string headline = _("Abort Catalog Configuration");
- // popup message
- string msg = _("Abort the catalog configuration?
- All changes will be lost.");
- if ( Popup::YesNoHeadline( headline, msg ) ) {
- exit = true;
- }
- }
- else
- {
- current = (integer) UI::QueryWidget( `id( `table ), `CurrentItem );
-
- y2debug( "Current item: %1", current );
-
- map<string, any> sourceState = sourceStatesOut[ current ]:$[];
- integer id = sourceState[ "SrcId" ]:-1;
-
- if ( id < 0 ) {
- y2internal( "Unable to determine source id" );
- continue;
- }
-
- if ( input == `replace )
- {
- map generalData = Pkg::SourceGeneralData( id );
- string url = generalData[ "url" ]:"";
- boolean auto_refresh = sourceState["autorefresh"]:true;
- boolean plaindir = generalData["type"]:"YaST" == plaindir_type;
-
- do {
- // change schema if the source type is plaindir
- // to show the right popup dialog
- if (plaindir)
- {
- map parsed = URL::Parse(url);
- parsed["scheme"] = "pkg";
- url = URL::Build(parsed);
- }
-
- url = editUrl( url );
-
- if ( size( url ) == 0 ) break;
- createResult = createSource( url );
- if ( createResult == `ok ) {
- deleteSource( current );
- fillTable();
- }
- } while ( createResult == `again );
- }
- else if ( input == `refresh )
- {
- Pkg::SourceRefreshNow (id);
- fillTable ();
- /* map generalData = Pkg::SourceGeneralData( id );
- string url = generalData[ "url" ]:"";
-
- do {
- // url = editUrl( url );
- if ( size( url ) == 0 ) break;
- deleteSource( current );
- createResult = createSource( url );
- if ( createResult == `ok ) {
- fillTable();
- }
- } while ( createResult == `again );*/
- }
- else if ( input == `delete )
- {
- // yes-no popup
- if ( Popup::YesNo( _("Delete the selected catalog from the list?") ) )
- {
- deleteSource( current );
- fillTable();
- }
- }
- else if ( input == `enable )
- {
- boolean state = sourceState[ "enabled" ]:true;
- state = !state;
- // corresponds to the "Enable/Disable" button
- string newstate = ( state ? _("On") : _("Off") );
- UI::ChangeWidget( `id( `table ), `Item( current, 0 ), newstate );
- sourceState[ "enabled" ] = state;
- sourceStatesOut[ current ] = sourceState;
- }
- else if ( input == `refresh_on_off )
- {
- integer source_id = sourceState["SrcId"]:0;
- map src_data = Pkg::SourceGeneralData (source_id);
- string type = src_data["type"]:"UnitedLinux";
-
- boolean state = sourceState[ "autorefresh" ]:true;
- if (type == "PlainDir" && ! state)
- {
- // popup message
- Popup::Message (_("For the selected source, refresh
- cannot be set."));
- }
- else
- {
- state = !state;
- }
- // corresponds to the "Enable/Disable" button
- string newstate = ( state ? _("On") : _("Off") );
- UI::ChangeWidget( `id( `table ), `Item( current, 1 ), newstate );
- sourceState["autorefresh"] = state;
- sourceStatesOut[ current ] = sourceState;
- }
- }
-
- } until ( exit );
-
- UI::CloseDialog();
-
- y2debug( "Return: %1", input );
-
- return input;
- }
-
- symbol StoreSource () {
- string url = SourceDialogs::GetURL ();
- if (url == "slp://")
- {
- string service = SourceManager::AddSourceTypeSLP ();
- y2milestone ("Trying to add source '%1'", service);
- if (service != nil)
- {
- // add the installation source
- symbol createResult = createSource(service);
- y2milestone ("Adding source result: %1", createResult);
- return `next;
- }
- return `back;
- }
- if (createSource(url) == `again)
- return `back;
- return `next;
- }
-
- boolean restore = Pkg::SourceStartManager( false );
- if( ! restore )
- {
- // #210514 (L3): unconditionally removing the sources is BAD.
- // Usually it is just a temporary error because of misconfigured proxy.
- boolean cleanup = Popup::AnyQuestion( // [1]
- Label::ErrorMsg(),
- // Error popup (part 1)
- _("There were errors when restoring the source configuration.
- Not all sources are available for configuration.
- ") + Pkg::LastError() + "\n\n" +
- // Error popup (part 2): Yes/No question.
- // "immediately" is important: because of stupid design [2],
- // they will be removed even if the user then chooses Abort :(
- _("Do you want to immediately remove these sources?"),
- Label::YesButton(), Label::NoButton(), `focus_no);
- // Notes irrelevant for translators:
- // [1]: we want the focus on "No"; Popup::YesNo is too specialized
- // [2]: using SourceManager and not just PersistentStorage in inst_source
-
- // delete the broken sources from the persistent store
- if (cleanup) {
- Pkg::SourceCleanupBroken();
- }
- }
-
- sourceStatesIn = Pkg::SourceEditGet();
- y2milestone( "Found sources: %1", sourceStatesIn);
- sourceStatesOut = sourceStatesIn;
-
- map<string,any> aliases = $[
- "summary" : ``(SummaryDialog ()),
- "type" : ``(SourceDialogs::TypeDialog ()),
- "edit" : ``(SourceDialogs::EditDialog ()),
- "store" : ``(StoreSource ())
- ];
-
- map sequence = $[
- "ws_start" : "summary",
- "summary" : $[
- `add : "type",
- `edit : "edit",
- `abort : `abort,
- `next : `next,
- ],
- "type" : $[
- `next : "edit",
- `finish : "store",
- `abort : `abort,
- ],
- "edit" : $[
- `next : "store",
- `abort : `abort,
- ],
- "store" : $[
- `next : "summary",
- `abort : `abort,
- ],
- ];
-
- y2milestone ("Starting source sequence");
- symbol ret = Sequencer::Run (aliases, sequence);
- if (ret == `next && Mode::normal ())
- ret = `restart_menu;
-
- UI::CloseDialog ();
- return ret;
-
- } // EOF
-