From 3bd8fbe081d98a6fef330c7e18601355420dcd09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Katar=C3=ADna=20Mach=C3=A1lkov=C3=A1?= Date: Tue, 16 Dec 2008 12:43:10 +0000 Subject: [PATCH 01/50] Consistent widget focusing (#435992) svn path=/branches/SuSE-Code-11-Branch/nfs-client/; revision=54164 --- VERSION | 2 +- package/yast2-nfs-client.changes | 7 +++++++ src/ui.ycp | 10 +++++----- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/VERSION b/VERSION index 87877ec..ead81cc 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.17.10 +2.17.11 diff --git a/package/yast2-nfs-client.changes b/package/yast2-nfs-client.changes index 5a7859e..72fdda3 100644 --- a/package/yast2-nfs-client.changes +++ b/package/yast2-nfs-client.changes @@ -1,3 +1,10 @@ +------------------------------------------------------------------- +Tue Dec 16 13:37:37 CET 2008 - kmachalkova@suse.cz + +- Consistent setting of widget focus esp. when embedded in partitioner + (bnc#435992) +- 2.17.11 + ------------------------------------------------------------------- Thu Dec 11 15:51:48 CET 2008 - kmachalkova@suse.cz diff --git a/src/ui.ycp b/src/ui.ycp index d83c41e..63c0772 100644 --- a/src/ui.ycp +++ b/src/ui.ycp @@ -537,11 +537,6 @@ rights.

") + fw_cwm_widget["help"]:""; UI::ChangeWidget (`id(`fstable), `Items, FstabTableItems (nfs_entries)); EnableDisableButtons(); - // Kludge, because a `Table still does not have a shortcut. - // Simple to solve here: there's only the table and buttons, - // so it is OK to always set focus to the table - UI::SetFocus (`id (`fstable)); - } void InitSettings( ) @@ -665,6 +660,11 @@ rights.

") + fw_cwm_widget["help"]:""; InitFstabEntries(); + // Kludge, because a `Table still does not have a shortcut. + // Simple to solve here: there's only the table and buttons, + // so it is OK to always set focus to the table + UI::SetFocus (`id (`fstable)); + map event = nil; any ret = nil; integer entryno = -1; From 9ce4311834172cd37f2379ebe6e49443608bde59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20=C5=A0rain?= Date: Fri, 25 Sep 2009 06:21:48 +0000 Subject: [PATCH 02/50] merged the tmp/SLE-11-SP1-Stash branch svn path=/branches/SuSE-Code-11-SP1-Branch/nfs-client/; revision=58763 --- VERSION | 2 +- package/yast2-nfs-client.changes | 7 +++++++ src/Nfs.ycp | 9 ++++++--- src/ui.ycp | 32 ++++++++++++++++++++++++++++++-- 4 files changed, 44 insertions(+), 6 deletions(-) diff --git a/VERSION b/VERSION index ead81cc..0b8ec8e 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.17.11 +2.17.12 diff --git a/package/yast2-nfs-client.changes b/package/yast2-nfs-client.changes index 72fdda3..09d1a89 100644 --- a/package/yast2-nfs-client.changes +++ b/package/yast2-nfs-client.changes @@ -1,3 +1,10 @@ +------------------------------------------------------------------- +Wed Apr 8 16:37:35 CEST 2009 - kmachalkova@suse.cz + +- Do not use ag_showexports to show nfsv4-shared dirs on a server, + use Nfs::Mount and show directory listing instead (bnc#466454) +- 2.17.12 + ------------------------------------------------------------------- Tue Dec 16 13:37:37 CET 2008 - kmachalkova@suse.cz diff --git a/src/Nfs.ycp b/src/Nfs.ycp index 8267d59..d333cdf 100644 --- a/src/Nfs.ycp +++ b/src/Nfs.ycp @@ -450,10 +450,11 @@ the NFS client configuration.\n")); * @param share name of the exported directory * @param mpoint mount point (can be empty or nil, in this case it will be mounted in temporary directory) * @param options mount options - e.g. "ro,hard,intr", see man nfs + * @param type nfs type (nfs vs. nfsv4) - if empty, 'nfs' is used * @return string directory where volume was mounted or nil if mount failed */ - global define string Mount(string server, string share, string mpoint, string options) ``{ + global define string Mount(string server, string share, string mpoint, string options, string type) ``{ if (size(server) == 0 || size(share) == 0) { @@ -525,7 +526,9 @@ the NFS client configuration.\n")); } // build mount command - string command = sformat("/bin/mount %1 %2:%3 %4", (size(options) > 0) ? "-o " + options : "", server, share, mpoint); + string command = sformat("/bin/mount %1 %2 %3:%4 %5", (size(options) > 0) ? "-o " + options : "", + "-t " + (size(type) > 0 ? type : "nfs"), + server, share, mpoint); // execute mount command return (SCR::Execute(.target.bash, command) == 0) ? mpoint : nil; @@ -551,7 +554,7 @@ the NFS client configuration.\n")); string type = (string) (m["vfstype"]:nil); string file = (string) (m["file"]:nil); - if (type == "nfs" && file == mpoint) + if ( (type == "nfs" || type == "nfs4") && file == mpoint) { found = true; } diff --git a/src/ui.ycp b/src/ui.ycp index 63c0772..f25b6d8 100644 --- a/src/ui.ycp +++ b/src/ui.ycp @@ -242,6 +242,7 @@ `PushButton (`id (`pathent_list), _("&Select")) ) ), + `Left( `CheckBox(`id(`nfs4), _("NFS&v4 Share"), nfs4)), `Left( TextAndButton ( `TextEntry(`id(`mountent), @@ -255,7 +256,6 @@ ), // textentry label `VSpacing(0.2), - `Left( `CheckBox(`id(`nfs4), _("NFS&v4 Share"), nfs4)), `TextEntry(`id(`optionsent), _("O&ptions"), options), `VSpacing(0.2), `HBox( @@ -323,13 +323,41 @@ which probably blocks the network scanning."); else if (ret == `pathent_list) { string server = (string) UI::QueryWidget(`id(`serverent), `Value); + boolean v4 = (boolean) UI::QueryWidget(`id(`nfs4), `Value); + + if (!CheckHostName (server)) + { + UI::SetFocus (`id (`serverent)); + continue; + } + UI::OpenDialog ( `Label ( // Popup dialog, %1 is a host name sformat (_("Getting directory list for \"%1\"..."), server) )); - list dirs = (list) SCR::Read (.net.showexports, server); + list dirs = []; + + // showmounts does not work for nfsv4 (#466454) + if (v4) + { + string tmpdir = Nfs::Mount(server, "/", nil, "ro", "nfs4"); + + // This is completely stupid way how to explore what can be mounted + // and I even don't know if it is correct. Maybe 'find tmpdir -xdev -type d' + // should be used instead. No clue :( + dirs = maplist( string dirent, (list ) SCR::Read(.target.dir, tmpdir), { + return "/" + dirent; + }); + dirs = prepend(dirs, "/"); + Nfs::Unmount( tmpdir ); + } + else + { + dirs = (list) SCR::Read (.net.showexports, server); + } + if (dirs == nil) { dirs = ["internal error"]; From 9768caa479156819536e556cb0e736d7d1c4d5c7 Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Tue, 21 Jun 2011 16:30:54 +0000 Subject: [PATCH 03/50] Fixed attempt to install rpmbind to inst-sys during installation(bnc#621197) svn path=/branches/SuSE-Code-11-SP2-Branch/nfs-client/; revision=64522 --- package/yast2-nfs-client.changes | 6 ++++++ src/Nfs.ycp | 15 +++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/package/yast2-nfs-client.changes b/package/yast2-nfs-client.changes index 09d1a89..862af62 100644 --- a/package/yast2-nfs-client.changes +++ b/package/yast2-nfs-client.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Tue Jun 21 18:24:39 CEST 2011 - jreidinger@suse.cz + +- Fixed attempt to install rpmbind to inst-sys during installation + (bnc#621197) + ------------------------------------------------------------------- Wed Apr 8 16:37:35 CEST 2009 - kmachalkova@suse.cz diff --git a/src/Nfs.ycp b/src/Nfs.ycp index d333cdf..62f13cb 100644 --- a/src/Nfs.ycp +++ b/src/Nfs.ycp @@ -28,6 +28,7 @@ import "SuSEFirewall"; import "Progress"; import "PackageSystem"; + import "PackagesProposal"; import "Wizard"; include "nfs/routines.ycp"; @@ -283,8 +284,18 @@ if (nfs4_enabled) required_packages = add( required_packages, "nfsidmap"); - if ( !PackageSystem::CheckAndInstallPackagesInteractive( required_packages ) ) - return false; + if (Mode::installation()) + { + foreach (string p, required_packages, + { + PackagesProposal::AddResolvables ("yast2-nfs-client", `package, [p]); + }); + } + else + { + if ( !PackageSystem::CheckAndInstallPackagesInteractive( required_packages ) ) + return false; + } return true; } From c86fe665a69124d0f92f1b25cb877b389f96d409 Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Wed, 22 Jun 2011 12:34:59 +0000 Subject: [PATCH 04/50] allow to set version of nfs on command line and also fix passing default value (bnc#681275) svn path=/branches/SuSE-Code-11-SP2-Branch/nfs-client/; revision=64543 --- src/nfs.ycp | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/nfs.ycp b/src/nfs.ycp index ac6937d..58aebbe 100644 --- a/src/nfs.ycp +++ b/src/nfs.ycp @@ -93,6 +93,14 @@ boolean NfsAddHandler (map options) { return false; } + string type = options["type"]:"nfs"; + if (type != "nfs" && type != "nfs4") + { + Report::Error (_("Unknown value for option \"type\".")); + return false; + } + options["vfstype"] = type; + nfs_entries = add (nfs_entries, (map) options); Nfs::nfs_entries = nfs_entries; return true; @@ -116,6 +124,18 @@ boolean NfsEditHandler (map options) { CommandLine::Print (_("No NFS mount specified.")); return false; } + + string type = options["type"]:"nfs"; + if (type != "nfs" && type != "nfs4") + { + Report::Error (_("Unknown value for option \"type\".")); + return false; + } + if (haskey(options,"type")) + { + options["vfstype"] = type; + } + list entries = []; integer i = 0; foreach (map entry, nfs_entries, { @@ -260,12 +280,18 @@ map cmdline_description = $[ // fstab(5): fs_mntops "help" : _("Mount options"), ], + "type" : $[ + "type" : "string", // nfs or nfs4 + // command line option help + // fstab(5): fs_type + "help" : _("File system id, supported nfs and nfs4. Default value is nfs."), + ], ], "mappings" : $[ "list" : [], - "add" : ["spec", "file", "mntops",], + "add" : ["spec", "file", "mntops","type",], // either of spec and file is key - "edit" : ["spec", "file", "mntops",], + "edit" : ["spec", "file", "mntops","type",], // either of spec and file is key "delete" : ["spec", "file",], ] From 25895b23279aeb527616eb02a01457c170dbde51 Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Mon, 27 Jun 2011 10:45:54 +0000 Subject: [PATCH 05/50] fix enablement of NFSv4 in autoyast (bnc#684859) svn path=/branches/SuSE-Code-11-SP2-Branch/nfs-client/; revision=64596 --- src/Nfs.ycp | 14 +++++++++----- src/ui.ycp | 4 ++-- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/Nfs.ycp b/src/Nfs.ycp index 62f13cb..6131729 100644 --- a/src/Nfs.ycp +++ b/src/Nfs.ycp @@ -72,7 +72,7 @@ */ global list non_nfs_entries = []; - global boolean nfs4_enabled = false; + global boolean nfs4_enabled = nil; global string idmapd_domain = ""; @@ -124,6 +124,11 @@ if ( !haskey(s, "vfstype") ) { s["vfstype"] = "nfs"; + } else { + if (s["vfstype"]:"nfs" == "nfs4") + { + nfs4_enabled = true; + } } return s; @@ -357,16 +362,15 @@ the NFS client configuration.\n")); Service::Enable("nfsboot"); } - if(nfs4_enabled) + if(nfs4_enabled == true) { SCR::Write(.sysconfig.nfs.NFS4_SUPPORT,"yes"); SCR::Write(.etc.idmapd_conf, ["Domain", idmapd_domain] ); } - else + else if (nfs4_enabled == false) { SCR::Write(.sysconfig.nfs.NFS4_SUPPORT,"no"); } - boolean progress_orig = Progress::set (false); SuSEFirewall::WriteOnly (); Progress::set (progress_orig); @@ -518,7 +522,7 @@ the NFS client configuration.\n")); { if (Service::Start( portmapper ) == false) { - y2warning( sformat("%1 cannot be started", portmapper) ); + y2warning("%1 cannot be started", portmapper); return nil; } } diff --git a/src/ui.ycp b/src/ui.ycp index f25b6d8..cc71f8b 100644 --- a/src/ui.ycp +++ b/src/ui.ycp @@ -570,8 +570,8 @@ rights.

") + fw_cwm_widget["help"]:""; void InitSettings( ) { CWMFirewallInterfaces::OpenFirewallInit (fw_cwm_widget, ""); - UI::ChangeWidget(`id(`enable_nfs4), `Value, Nfs::nfs4_enabled); - UI::ChangeWidget( `id(`nfs4_domain), `Enabled, Nfs::nfs4_enabled); + UI::ChangeWidget(`id(`enable_nfs4), `Value, Nfs::nfs4_enabled != false); + UI::ChangeWidget( `id(`nfs4_domain), `Enabled, Nfs::nfs4_enabled != false); UI::ChangeWidget(`id(`nfs4_domain), `Value, Nfs::idmapd_domain); } From 4aa5eb01f12cdad143208df17b9e065d9e2a86c5 Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Mon, 27 Jun 2011 10:51:54 +0000 Subject: [PATCH 06/50] changes svn path=/branches/SuSE-Code-11-SP2-Branch/nfs-client/; revision=64597 --- package/yast2-nfs-client.changes | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/package/yast2-nfs-client.changes b/package/yast2-nfs-client.changes index 862af62..9104ba1 100644 --- a/package/yast2-nfs-client.changes +++ b/package/yast2-nfs-client.changes @@ -1,3 +1,11 @@ +------------------------------------------------------------------- +Mon Jun 27 10:50:58 UTC 2011 - jreidinger@novell.com + +- fix enablement of NFSv4 in autoyast (bnc#684859) +- allow to set version of nfs on command line and also fix passing + default value (bnc#681275) +- 2.17.13 + ------------------------------------------------------------------- Tue Jun 21 18:24:39 CEST 2011 - jreidinger@suse.cz From cc101fb4745da22a8c19919c63b2d16948d59423 Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Mon, 27 Jun 2011 10:52:15 +0000 Subject: [PATCH 07/50] versin bump svn path=/branches/SuSE-Code-11-SP2-Branch/nfs-client/; revision=64598 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 0b8ec8e..9ffb7f4 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.17.12 +2.17.13 From 5a0380590198d643a6a061972be997199c93207d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Katar=C3=ADna=20Mach=C3=A1lkov=C3=A1?= Date: Thu, 4 Feb 2010 12:16:13 +0000 Subject: [PATCH 08/50] Use ButtonBoxes, use Wizard::OpenOKDialog svn path=/trunk/nfs-client/; revision=60690 --- src/ui.ycp | 14 +++++++------- src/wizards.ycp | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/ui.ycp b/src/ui.ycp index cc71f8b..30f7a73 100644 --- a/src/ui.ycp +++ b/src/ui.ycp @@ -73,7 +73,7 @@ `SelectionBox (`id (`items), title, items), `VSpacing(10) ), - `HBox ( + `ButtonBox ( `PushButton (`id (`ok), `opt (`default, `key_F10), Label::OKButton ()), `PushButton (`id (`cancel), `opt (`key_F9), @@ -258,7 +258,7 @@ `VSpacing(0.2), `TextEntry(`id(`optionsent), _("O&ptions"), options), `VSpacing(0.2), - `HBox( + `ButtonBox( `PushButton(`id(`ok), `opt(`default, `key_F10), Label::OKButton()), `PushButton(`id(`cancel), `opt (`key_F9), Label::CancelButton()), `PushButton(`id(`help), `opt (`key_F1), Label::HelpButton())), @@ -679,12 +679,12 @@ rights.

") + fw_cwm_widget["help"]:""; nfs_entries = Nfs::nfs_entries; // dialog heading - Wizard::SetContentsButtons(_("NFS Client Configuration"), + Wizard::SetContents(_("NFS Client Configuration"), MainDialogLayout(), help_text1, - Label::BackButton (), - Label::OKButton ()); - Wizard::HideBackButton(); - Wizard::SetAbortButton(`abort, Label::CancelButton()); + false, + true); + //Wizard::HideBackButton(); + //Wizard::SetAbortButton(`abort, Label::CancelButton()); InitFstabEntries(); diff --git a/src/wizards.ycp b/src/wizards.ycp index 91b2b4e..313d372 100644 --- a/src/wizards.ycp +++ b/src/wizards.ycp @@ -54,7 +54,7 @@ any NfsSequence () ] ]; - Wizard::CreateDialog (); + Wizard::OpenOKDialog (); Wizard::SetDesktopIcon ("nfs"); any ret = Sequencer::Run (aliases, sequence); From b6a095d94359aab6f0db891206c413f29cb93da8 Mon Sep 17 00:00:00 2001 From: Martin Vidner Date: Thu, 22 Nov 2012 15:55:41 +0100 Subject: [PATCH 09/50] added fix for handling button OK bnc#589541 svn path=/trunk/nfs-client/; revision=61434 Conflicts: VERSION package/yast2-nfs-client.changes --- VERSION | 2 +- package/yast2-nfs-client.changes | 12 ++++++++++++ src/ui.ycp | 8 ++++++-- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/VERSION b/VERSION index 9ffb7f4..1f085b8 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.17.13 +2.17.14 diff --git a/package/yast2-nfs-client.changes b/package/yast2-nfs-client.changes index 9104ba1..436e3ff 100644 --- a/package/yast2-nfs-client.changes +++ b/package/yast2-nfs-client.changes @@ -1,3 +1,15 @@ +------------------------------------------------------------------- +Wed May 26 16:58:39 CEST 2010 - kmachalkova@suse.cz + +- Fixed handling of return symbols (buggy patch for bnc#589541, now + bnc#608166) + +------------------------------------------------------------------- +Mon Mar 22 15:22:12 CET 2010 - juhliarik@suse.cz + +- added fix for problem with OK button (bnc#589541) +- 2.17.14 + ------------------------------------------------------------------- Mon Jun 27 10:50:58 UTC 2011 - jreidinger@novell.com diff --git a/src/ui.ycp b/src/ui.ycp index 30f7a73..5420119 100644 --- a/src/ui.ycp +++ b/src/ui.ycp @@ -180,7 +180,7 @@ } /** * Ask user for an entry. - * @param fstab_ent $["spec": "file": "mntopts":] or nil + * @param fstab_ent $["spec": "file": "mntops":] or nil * @param existing list of fstab entries for duplicate mount-point checking * @return a nfs_entry or nil */ @@ -701,7 +701,11 @@ rights.

") + fw_cwm_widget["help"]:""; { event = UI::WaitForEvent (); ret = event["ID"]:nil; - if (ret == `cancel) + if (ret == `ok) + { + ret = `next; + } + else if (ret == `cancel) { ret = `abort; } From 56ad419f964518b446a2481bdec1c70dd160dd4b Mon Sep 17 00:00:00 2001 From: Martin Vidner Date: Tue, 23 Mar 2010 12:39:01 +0000 Subject: [PATCH 10/50] Taking the package (back) after Bubli has changed teams. svn path=/trunk/nfs-client/; revision=61452 --- MAINTAINER | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINER b/MAINTAINER index 354f77d..039ad69 100644 --- a/MAINTAINER +++ b/MAINTAINER @@ -1 +1 @@ -Katarina Machalkova +Martin Vidner From 1d4028267189479e50ae372157bda2e871fd2fb7 Mon Sep 17 00:00:00 2001 From: Martin Vidner Date: Thu, 22 Nov 2012 15:58:50 +0100 Subject: [PATCH 11/50] Adjusted the changelog of the ported changes. Conflicts: package/yast2-nfs-client.changes --- package/yast2-nfs-client.changes | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/package/yast2-nfs-client.changes b/package/yast2-nfs-client.changes index 436e3ff..4b9a51e 100644 --- a/package/yast2-nfs-client.changes +++ b/package/yast2-nfs-client.changes @@ -1,13 +1,10 @@ ------------------------------------------------------------------- -Wed May 26 16:58:39 CEST 2010 - kmachalkova@suse.cz +Mon Oct 15 08:28:10 UTC 2012 - mfilka@suse.com -- Fixed handling of return symbols (buggy patch for bnc#589541, now - bnc#608166) - -------------------------------------------------------------------- -Mon Mar 22 15:22:12 CET 2010 - juhliarik@suse.cz - -- added fix for problem with OK button (bnc#589541) +- ported several old fixes from master branch: + - Fixed handling of return symbols (buggy patch for bnc#589541, now + bnc#608166) + - added fix for problem with OK button (bnc#589541) - 2.17.14 ------------------------------------------------------------------- From e6749b7c6279249502a912da8f59659d8d48269d Mon Sep 17 00:00:00 2001 From: Martin Vidner Date: Thu, 22 Nov 2012 15:59:57 +0100 Subject: [PATCH 12/50] Base server hostname combobox on existing values - bnc#547983 Conflicts: package/yast2-nfs-client.changes --- package/yast2-nfs-client.changes | 1 + src/Nfs.ycp | 31 ++++++++++++++++--------------- src/ui.ycp | 28 ++++++++++++++++++++++++---- 3 files changed, 41 insertions(+), 19 deletions(-) diff --git a/package/yast2-nfs-client.changes b/package/yast2-nfs-client.changes index 4b9a51e..eec3a0d 100644 --- a/package/yast2-nfs-client.changes +++ b/package/yast2-nfs-client.changes @@ -2,6 +2,7 @@ Mon Oct 15 08:28:10 UTC 2012 - mfilka@suse.com - ported several old fixes from master branch: + - Base server hostname combobox on existing values - bnc#547983 - Fixed handling of return symbols (buggy patch for bnc#589541, now bnc#608166) - added fix for problem with OK button (bnc#589541) diff --git a/src/Nfs.ycp b/src/Nfs.ycp index 6131729..c777b5e 100644 --- a/src/Nfs.ycp +++ b/src/Nfs.ycp @@ -117,22 +117,23 @@ } }); - //Backwards compatibility: with FaTE#302031, we support nfsv4 mounts - //thus we need to keep info on nfs version (v3 vs. v4) - //But older AY profiles might not contain this element - //so let's assume nfsv3 in that case (#395850) - if ( !haskey(s, "vfstype") ) - { - s["vfstype"] = "nfs"; - } else { - if (s["vfstype"]:"nfs" == "nfs4") - { - nfs4_enabled = true; - } - } + //Backwards compatibility: with FaTE#302031, we support nfsv4 mounts + //thus we need to keep info on nfs version (v3 vs. v4) + //But older AY profiles might not contain this element + //so let's assume nfsv3 in that case (#395850) + if ( !haskey(s, "vfstype") ) + { + s["vfstype"] = "nfs"; + } else { + if (s["vfstype"]:"nfs" == "nfs4") + { + nfs4_enabled = true; + } + } return s; }); + if (missing) { return false; @@ -279,10 +280,10 @@ Progress::set(progress_orig); portmapper = FindPortmapper(); - //There is neither rpcbind nor portmap + //There is neither rpcbind nor portmap if ( portmapper == "" ) { - //so let's install rpcbind (default since #423026) + //so let's install rpcbind (default since #423026) required_packages = add( required_packages, "rpcbind" ); portmapper = "rpcbind"; } diff --git a/src/ui.ycp b/src/ui.ycp index 5420119..53310c6 100644 --- a/src/ui.ycp +++ b/src/ui.ycp @@ -57,6 +57,11 @@ list hosts = nil; + /** + * List of already defined nfs mount points + */ + list< map > nfs_entries = Nfs::nfs_entries; + /** * Let the user choose one of a list of items * @param title selectionbox title @@ -178,6 +183,7 @@ `Bottom (button) ); } + /** * Ask user for an entry. * @param fstab_ent $["spec": "file": "mntops":] or nil @@ -213,6 +219,19 @@ servers = [ proposed_server ]; } + // append already defined servers - bug #547983 + foreach( map nfs_entry, nfs_entries, + { + term couple = SpecToServPath( nfs_entry[ "spec"]:""); + string known_server = couple[0]:""; + + if( !contains( servers, known_server)) + servers = add( servers, known_server); + }); + + servers = sort( servers); + // + UI::OpenDialog( `opt(`decorated), `HBox( @@ -232,7 +251,8 @@ ), `HSpacing(0.5), TextAndButton ( - `TextEntry(`id(`pathent), + `InputField( `id(`pathent), + `opt(`hstretch), // textentry label _("&Remote Directory"), pth), // pushbutton label, @@ -245,7 +265,8 @@ `Left( `CheckBox(`id(`nfs4), _("NFS&v4 Share"), nfs4)), `Left( TextAndButton ( - `TextEntry(`id(`mountent), + `InputField(`id(`mountent), + `opt(`hstretch), // textentry label _("&Mount Point (local)"), mount), // button label @@ -256,7 +277,7 @@ ), // textentry label `VSpacing(0.2), - `TextEntry(`id(`optionsent), _("O&ptions"), options), + `InputField(`id(`optionsent), `opt( `hstretch), _("O&ptions"), options), `VSpacing(0.2), `ButtonBox( `PushButton(`id(`ok), `opt(`default, `key_F10), Label::OKButton()), @@ -468,7 +489,6 @@ read the man page mount(8).

"); ]; map fw_cwm_widget = CWMFirewallInterfaces::CreateOpenFirewallWidget (fw_settings); - list< map > nfs_entries = Nfs::nfs_entries; map modify_line = $[]; // Help, part 1 of 3 From 34a9945bc11d3f9800db6f9e6027a8f96ad4c689 Mon Sep 17 00:00:00 2001 From: Michal Filka Date: Fri, 26 Oct 2012 13:56:27 +0200 Subject: [PATCH 13/50] autoinstallation fails to enable rpcbind / portmapper - bnc#744357 svn path=/trunk/nfs-client/; revision=67463 Conflicts: package/yast2-nfs-client.changes Conflicts: package/yast2-nfs-client.changes --- package/yast2-nfs-client.changes | 1 + src/Nfs.ycp | 1 + 2 files changed, 2 insertions(+) diff --git a/package/yast2-nfs-client.changes b/package/yast2-nfs-client.changes index eec3a0d..945b11f 100644 --- a/package/yast2-nfs-client.changes +++ b/package/yast2-nfs-client.changes @@ -2,6 +2,7 @@ Mon Oct 15 08:28:10 UTC 2012 - mfilka@suse.com - ported several old fixes from master branch: + - autoinstallation fails to enable portmapper/rpcbind service - bnc#744357 - Base server hostname combobox on existing values - bnc#547983 - Fixed handling of return symbols (buggy patch for bnc#589541, now bnc#608166) diff --git a/src/Nfs.ycp b/src/Nfs.ycp index c777b5e..7ba96c3 100644 --- a/src/Nfs.ycp +++ b/src/Nfs.ycp @@ -354,6 +354,7 @@ the NFS client configuration.\n")); // Service::Adjust ("nfs", "disable"); // what if autofs needs it? }*/ + portmapper = FindPortmapper(); if (size (nfs_entries) != 0) { Service::Enable( portmapper ); From f7d8f4290bc3f61563199c17eab15488fc02c67b Mon Sep 17 00:00:00 2001 From: Michal Filka Date: Fri, 26 Oct 2012 13:57:20 +0200 Subject: [PATCH 14/50] removed some dead code, whitespaces svn path=/trunk/nfs-client/; revision=67465 Conflicts: src/Nfs.ycp Conflicts: package/yast2-nfs-client.changes --- package/yast2-nfs-client.changes | 1 + src/Nfs.ycp | 9 ++------- src/ui.ycp | 15 ++++++--------- 3 files changed, 9 insertions(+), 16 deletions(-) diff --git a/package/yast2-nfs-client.changes b/package/yast2-nfs-client.changes index 945b11f..89883e1 100644 --- a/package/yast2-nfs-client.changes +++ b/package/yast2-nfs-client.changes @@ -2,6 +2,7 @@ Mon Oct 15 08:28:10 UTC 2012 - mfilka@suse.com - ported several old fixes from master branch: + - removed some dead code, whitespaces - autoinstallation fails to enable portmapper/rpcbind service - bnc#744357 - Base server hostname combobox on existing values - bnc#547983 - Fixed handling of return symbols (buggy patch for bnc#589541, now diff --git a/src/Nfs.ycp b/src/Nfs.ycp index 7ba96c3..995820c 100644 --- a/src/Nfs.ycp +++ b/src/Nfs.ycp @@ -349,11 +349,6 @@ the NFS client configuration.\n")); return false; } -/* if (size (nfs_entries) == 0) - { - // Service::Adjust ("nfs", "disable"); // what if autofs needs it? - }*/ - portmapper = FindPortmapper(); if (size (nfs_entries) != 0) { @@ -610,8 +605,8 @@ the NFS client configuration.\n")); return true; } - /** - * Return required packages for auto-installation + /** + * Return required packages for auto-installation * @return map of packages to be installed and to be removed */ global define map AutoPackages() ``{ diff --git a/src/ui.ycp b/src/ui.ycp index 53310c6..a36ddef 100644 --- a/src/ui.ycp +++ b/src/ui.ycp @@ -129,7 +129,7 @@ /* Return convenient hostname (FaTE #302863) to be proposed * i.e. nfs + current domain (nfs. + suse.cz) - * @return string proposed hostname + * @return string proposed hostname */ define string ProposeHostname() { string ret = ""; @@ -586,7 +586,7 @@ rights.

") + fw_cwm_widget["help"]:""; EnableDisableButtons(); } - + void InitSettings( ) { CWMFirewallInterfaces::OpenFirewallInit (fw_cwm_widget, ""); @@ -594,16 +594,16 @@ rights.

") + fw_cwm_widget["help"]:""; UI::ChangeWidget( `id(`nfs4_domain), `Enabled, Nfs::nfs4_enabled != false); UI::ChangeWidget(`id(`nfs4_domain), `Value, Nfs::idmapd_domain); } - + void SaveFstabEntries( ) { Nfs::nfs_entries = nfs_entries; } - + void SaveSettings( map event ) { CWMFirewallInterfaces::OpenFirewallStore (fw_cwm_widget, "", event); - Nfs::nfs4_enabled = (boolean) UI::QueryWidget(`id(`enable_nfs4),`Value); + Nfs::nfs4_enabled = (boolean) UI::QueryWidget(`id(`enable_nfs4),`Value); Nfs::idmapd_domain = (string) UI::QueryWidget(`id(`nfs4_domain),`Value); } @@ -613,9 +613,6 @@ rights.

") + fw_cwm_widget["help"]:""; // handle the events, enable/disable the button, show the popup if button clicked if ( UI::WidgetExists(`id("_cwm_firewall_details")) && UI::WidgetExists(`id("_cwm_open_firewall")) ) CWMFirewallInterfaces::OpenFirewallHandle (fw_cwm_widget, "", $[ "ID" : widget ]); - /*changed = - true || // TODO: fw changed, #44106 - true; // TODO: nfs changed*/ if ( UI::WidgetExists(`id(`fstable)) ) entryno = (integer) UI::QueryWidget(`id(`fstable), `CurrentItem); @@ -719,7 +716,7 @@ rights.

") + fw_cwm_widget["help"]:""; do { - event = UI::WaitForEvent (); + event = UI::WaitForEvent (); ret = event["ID"]:nil; if (ret == `ok) { From aac7b008b3f7b721a975ee8816d98900871345e1 Mon Sep 17 00:00:00 2001 From: Michal Filka Date: Fri, 26 Oct 2012 13:58:24 +0200 Subject: [PATCH 15/50] IPv6 addresses supported - bnc#719538 svn path=/trunk/nfs-client/; revision=67469 Conflicts: VERSION Conflicts: package/yast2-nfs-client.changes --- package/yast2-nfs-client.changes | 2 ++ src/routines.ycp | 32 +++++++++++++++++++++++++------- testsuite/tests/r-check.out | 3 +++ testsuite/tests/r-check.ycp | 9 ++++++++- testsuite/tests/r-spec.out | 2 +- testsuite/tests/r-spec.ycp | 2 +- 6 files changed, 40 insertions(+), 10 deletions(-) diff --git a/package/yast2-nfs-client.changes b/package/yast2-nfs-client.changes index 89883e1..f2e9bd1 100644 --- a/package/yast2-nfs-client.changes +++ b/package/yast2-nfs-client.changes @@ -2,6 +2,8 @@ Mon Oct 15 08:28:10 UTC 2012 - mfilka@suse.com - ported several old fixes from master branch: + - updated testsuite + - IPv6 addresses supported - bnc#719538 - removed some dead code, whitespaces - autoinstallation fails to enable portmapper/rpcbind service - bnc#744357 - Base server hostname combobox on existing values - bnc#547983 diff --git a/src/routines.ycp b/src/routines.ycp index 2699454..d492d76 100644 --- a/src/routines.ycp +++ b/src/routines.ycp @@ -23,17 +23,29 @@ import "Package"; import "Report"; + import "IP"; + import "String"; /** * @param spec "server:/path/specification" * @return `couple("server", "/path/specification") */ define term SpecToServPath(string spec) ``{ - integer colonpos = findfirstof(spec, ":"); + // split using ":/" (because of IPv6) + integer path_begin = search( spec, ":/"); string serv = ""; - if (colonpos != nil) { - serv = substring(spec, 0, colonpos); - spec = substring(spec, colonpos+1); + + // no :/ inside => : or [/] + if( path_begin == nil ) + { + if(spec == filterchars(spec, "-_." + String::CAlnum() ) + ":") + // matches [a-zA-Z0-1.-_] and ends with colon? => : + path_begin = size( spec) -1; + } + + if (path_begin != nil) { + serv = substring(spec, 0, path_begin); + spec = substring(spec, path_begin+1); } return `couple(serv, spec); } @@ -68,16 +80,22 @@ * @return whether valid */ define boolean CheckHostName(string name) ``{ + string dirname_forbidden = ":"; + if (size(name) > 0 && size(name) < 50 && - name == filterchars(name, - "-_.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")) { + name == filterchars(name, "-_.:" + String::CAlnum() )) { + if( IP::Check( name)) + return true; + if( "" != filterchars( name, dirname_forbidden)) + return false; + return true; } else // error popup message Report::Error (sformat(_("The hostname entered is invalid. It must be shorter than 50 characters and only use -0-9, A-Z, a-z, dots, -, and _."))); +0-9, A-Z, a-z, dots, -, and _.:"))); return false; }; diff --git a/testsuite/tests/r-check.out b/testsuite/tests/r-check.out index 5b11de6..0f47c88 100644 --- a/testsuite/tests/r-check.out +++ b/testsuite/tests/r-check.out @@ -14,3 +14,6 @@ Return true Return false Return false Return false +Return true +Return false +Return true diff --git a/testsuite/tests/r-check.ycp b/testsuite/tests/r-check.ycp index f7cf6aa..b3416aa 100644 --- a/testsuite/tests/r-check.ycp +++ b/testsuite/tests/r-check.ycp @@ -19,6 +19,9 @@ string OK_Name = "foo.bar.com.tw"; string TooLongName = "123456789012345678901234567890123456789012345678901234567890"; string IllegalName = "Something:wrong"; + string IPv4 = "192.168.10.1"; + string IPv4_invalid= "192.168.10:1"; + string IPv6 = "fe80::219:d1ff:feac:fd10"; DUMP ("check_options"); TEST (``(check_options ("")), [], nil); @@ -37,5 +40,9 @@ TEST (``(CheckHostName (TooLongName)), [], nil); TEST (``(CheckHostName (IllegalName)), [], nil); // Too long & illegal char - TEST (``(CheckHostName (TooLongName + ":")), [], nil); + TEST (``(CheckHostName (TooLongName + "!")), [], nil); + // check IPv? adresses + TEST (``(CheckHostName (IPv4)), [], nil); + TEST (``(CheckHostName (IPv4_invalid)), [], nil); + TEST (``(CheckHostName (IPv6)), [], nil); } diff --git a/testsuite/tests/r-spec.out b/testsuite/tests/r-spec.out index d638b26..c2b6c25 100644 --- a/testsuite/tests/r-spec.out +++ b/testsuite/tests/r-spec.out @@ -4,5 +4,5 @@ Return `couple ("only.server.com", "") Return `couple ("", "nocolon.only.server.com") Return `couple ("", "/only/path") Return `couple ("", "/nocolon/only/path") -Return `couple ("two", "colons:used") +Return `couple ("fe80::219:d1ff:feac:fd10", "/path") Return `couple ("", "") diff --git a/testsuite/tests/r-spec.ycp b/testsuite/tests/r-spec.ycp index 600634b..1cb16c9 100644 --- a/testsuite/tests/r-spec.ycp +++ b/testsuite/tests/r-spec.ycp @@ -22,6 +22,6 @@ TEST (``(SpecToServPath ("nocolon.only.server.com")), [], nil); TEST (``(SpecToServPath (":/only/path")), [], nil); TEST (``(SpecToServPath ("/nocolon/only/path")), [], nil); - TEST (``(SpecToServPath ("two:colons:used")), [], nil); + TEST (``(SpecToServPath ("fe80::219:d1ff:feac:fd10:/path")), [], nil); TEST (``(SpecToServPath ("")), [], nil); } From ad2539d6a850fa08dcf88a7e872d9efc5d015210 Mon Sep 17 00:00:00 2001 From: Michal Filka Date: Thu, 20 Sep 2012 13:21:39 +0200 Subject: [PATCH 16/50] Fixed indentation. Conflicts: src/routines.ycp --- src/routines.ycp | 196 +++++++++++++++++++++++------------------------ 1 file changed, 98 insertions(+), 98 deletions(-) diff --git a/src/routines.ycp b/src/routines.ycp index d492d76..a19b4c9 100644 --- a/src/routines.ycp +++ b/src/routines.ycp @@ -27,13 +27,13 @@ import "String"; /** - * @param spec "server:/path/specification" - * @return `couple("server", "/path/specification") + * @param spec "server:/path/specification" + * @return `couple("server", "/path/specification") */ define term SpecToServPath(string spec) ``{ // split using ":/" (because of IPv6) integer path_begin = search( spec, ":/"); - string serv = ""; + string serv = ""; // no :/ inside => : or [/] if( path_begin == nil ) @@ -43,118 +43,118 @@ path_begin = size( spec) -1; } - if (path_begin != nil) { - serv = substring(spec, 0, path_begin); - spec = substring(spec, path_begin+1); - } - return `couple(serv, spec); + if (path_begin != nil) { + serv = substring(spec, 0, path_begin); + spec = substring(spec, path_begin+1); + } + return `couple(serv, spec); } /** * Creates a list of ui table items for nfs fstab entries - * @param fstab list of nfs fstab entries - * @return itemized table entries + * @param fstab list of nfs fstab entries + * @return itemized table entries * @example UI::ChangeWidget(`id(`fstable), `Items, FstabTableItems(nfs_entries)); */ define list FstabTableItems(list fstab) ``{ - integer count = 0; - return maplist(map entry, fstab, ``{ - term sp = SpecToServPath(entry["spec"]:""); - term it = `item(`id(count), - sp[0]:"" + " ", - sp[1]:"" + " ", - entry["file"]:"" + " ", - entry["vfstype"]:" ", - entry["mntops"]:"" + " "); - - count = count+1; - return it; - }); + integer count = 0; + return maplist(map entry, fstab, ``{ + term sp = SpecToServPath(entry["spec"]:""); + term it = `item(`id(count), + sp[0]:"" + " ", + sp[1]:"" + " ", + entry["file"]:"" + " ", + entry["vfstype"]:" ", + entry["mntops"]:"" + " "); + + count = count+1; + return it; + }); } /** * Check for the validity of a hostname: nonempty, shorter than 50 chars, * [-A-Za-z._]. If invalid, a message is displayed. - * @param name a hostname - * @return whether valid + * @param name a hostname + * @return whether valid */ define boolean CheckHostName(string name) ``{ string dirname_forbidden = ":"; - if (size(name) > 0 && - size(name) < 50 && - name == filterchars(name, "-_.:" + String::CAlnum() )) { + if (size(name) > 0 && + size(name) < 50 && + name == filterchars(name, "-_.:" + String::CAlnum() )) { if( IP::Check( name)) return true; if( "" != filterchars( name, dirname_forbidden)) return false; - return true; - } else - // error popup message - Report::Error (sformat(_("The hostname entered is invalid. It must be + return true; + } else + // error popup message + Report::Error (sformat(_("The hostname entered is invalid. It must be shorter than 50 characters and only use 0-9, A-Z, a-z, dots, -, and _.:"))); - return false; + return false; }; /** * Check if a mountpoint is in the fstab. If yes, display a message. - * @param fstab in .etc.fstab format (must contain the key "file") - * @param mpoint mount point - * @return is it there? + * @param fstab in .etc.fstab format (must contain the key "file") + * @param mpoint mount point + * @return is it there? */ define boolean IsMpInFstab(list fstab, string mpoint) ``{ - list tmp = filter(map fse, fstab, ``{ - return (fse["file"]:"" == mpoint); - }); - - if (size(tmp) == 0) - return false; - else - // error popup message - Report::Error (sformat(_("fstab already contains an entry + list tmp = filter(map fse, fstab, ``{ + return (fse["file"]:"" == mpoint); + }); + + if (size(tmp) == 0) + return false; + else + // error popup message + Report::Error (sformat(_("fstab already contains an entry with mount point '%1'."), mpoint)); - return true; + return true; }; /** * Check for the validity of a path/mountpoint: * nonempty, fewer than 70 chars, starts with a slash. * If invalid, a message is displayed. - * @param name path - * @return whether valid + * @param name path + * @return whether valid */ define boolean CheckPath(string name) ``{ - if (size(name) > 0 && - size(name) < 70 && - substring(name, 0, 1) == "/") - { - return true; - } - - // error popup message (spaces are now allowed) - Report::Error (sformat(_("The path entered is invalid. + if (size(name) > 0 && + size(name) < 70 && + substring(name, 0, 1) == "/") + { + return true; + } + + // error popup message (spaces are now allowed) + Report::Error (sformat(_("The path entered is invalid. It must be shorter than 70 characters and it must begin with a slash (/)."))); - return false; + return false; }; /** * Checks the nfs options for /etc/fstab: * nonempty, comma separated list of foo,nofoo,bar=baz (see nfs(5)) - * @param options options - * @return a translated string with error message, emtpy string if ok + * @param options options + * @return a translated string with error message, emtpy string if ok */ define string check_options (string options) ``{ - // To translators: error popup - if (size (options) == 0) return _("Empty option strings are not allowed."); - if (options == "defaults") return ""; + // To translators: error popup + if (size (options) == 0) return _("Empty option strings are not allowed."); + if (options == "defaults") return ""; - list option_list = splitstring (options, ","); + list option_list = splitstring (options, ","); //the options must be easy to sync with mount.c and nfsmount.c @@ -175,45 +175,45 @@ and it must begin with a slash (/)."))); integer i = 0; string current_option = ""; - // first fiter out non value options and its nooptions forms (see nfs(5)) - option_list = filter (string e, option_list, ``(!contains (non_value, e))); - non_value = maplist (string e, non_value, ``(sformat ("no%1", e))); - option_list = filter (string e, option_list, ``(!contains (non_value, e))); - option_list = filter (string e, option_list, ``(!contains (non_value1, e))); - - while (i < size (option_list)) - { - string opt = option_list[i]:""; - list value = splitstring (opt, "="); - string v0 = value[0]:""; - string v1 = value[1]:""; - // FIXME: this also triggers for "intr=bogus" - // To translators: error popup - if (!contains (with_value, v0)) return sformat (_("Unknown option: %1"), v0); - // To translators: error popup - if (size (value) != 2) return sformat (_("Invalid option: %1"), opt); - // To translators: error popup - if (v1 == "") return sformat (_("Empty value for option: %1"), v0); - i = i + 1; - } - - return ""; + // first fiter out non value options and its nooptions forms (see nfs(5)) + option_list = filter (string e, option_list, ``(!contains (non_value, e))); + non_value = maplist (string e, non_value, ``(sformat ("no%1", e))); + option_list = filter (string e, option_list, ``(!contains (non_value, e))); + option_list = filter (string e, option_list, ``(!contains (non_value1, e))); + + while (i < size (option_list)) + { + string opt = option_list[i]:""; + list value = splitstring (opt, "="); + string v0 = value[0]:""; + string v1 = value[1]:""; + // FIXME: this also triggers for "intr=bogus" + // To translators: error popup + if (!contains (with_value, v0)) return sformat (_("Unknown option: %1"), v0); + // To translators: error popup + if (size (value) != 2) return sformat (_("Invalid option: %1"), opt); + // To translators: error popup + if (v1 == "") return sformat (_("Empty value for option: %1"), v0); + i = i + 1; + } + + return ""; } /** * Strips a superfluous slash off the end of a pathname. - * @param p pathname - * @return stripped pathname + * @param p pathname + * @return stripped pathname */ define string StripExtraSlash (string p) ``{ - if (regexpmatch (p, "^.+/$")) - { - return regexpsub (p, "^(.+)/$", "\\1"); - } - else - { - return p; - } + if (regexpmatch (p, "^.+/$")) + { + return regexpsub (p, "^(.+)/$", "\\1"); + } + else + { + return p; + } } /** @@ -221,6 +221,6 @@ and it must begin with a slash (/)."))); * @return boolean true if portmap is installed */ define boolean IsPortmapperInstalled( string portmapper ) ``{ - return Package::Install( portmapper ); + return Package::Install( portmapper ); } } From 33de4ffccf55fcf5ee8b469783cd422f82a5c7ce Mon Sep 17 00:00:00 2001 From: Michal Filka Date: Thu, 20 Sep 2012 14:45:05 +0200 Subject: [PATCH 17/50] Fixed support for IPv6 addresses. 1) Allows IPv6 enclosed in square brackets. 2) Added support for IPv6 link-local. 3) Fixed writing IPv6 into fstab. All IPv6 addresses has to be enclosed in square brackets. Additional fix for bnc#719538 --- src/routines.ycp | 65 ++++++++++++++++++++++++++++++++++++++++++------ src/ui.ycp | 2 +- 2 files changed, 58 insertions(+), 9 deletions(-) diff --git a/src/routines.ycp b/src/routines.ycp index a19b4c9..8261983 100644 --- a/src/routines.ycp +++ b/src/routines.ycp @@ -73,6 +73,35 @@ }); } + /** + * If param contains IPv6 in one of its various forms, extracts it. + * + * @param ip a buffer with address + * @return IPv6 part of ip param, unchanged ip param otherwise + */ + define string ParseIpv6( string ip) + { + // if ip is closed in [ ] or contain % then it can be special case of IPv6 syntax, + // so extract ipv6 (see description later) and continue with check. + // + // IPv6 syntax: + // - pure ipv6 blob (e.g. f008::1) + // - ipv6 blob with link local suffix (e.g. f008::1%eth0) + // - dtto in square brackets (e.g. [f008::1%eth0] ) + if( regexpmatch( ip, "^\\[.*\\]") || regexpmatch( ip, "^[^][%]+(%[^][%]+){0,1}$")) + ip = regexpsub( ip, "^\\[?([^][%]+)(%[^][%]+){0,1}(\\]|$)", "\\1"); + + return ip; + } + + /** + * Checks if given entry is valid ip address + */ + define boolean CheckIp( string ip) + { + return IP::Check( ParseIpv6( ip) ); + } + /** * Check for the validity of a hostname: nonempty, shorter than 50 chars, * [-A-Za-z._]. If invalid, a message is displayed. @@ -80,22 +109,31 @@ * @return whether valid */ define boolean CheckHostName(string name) ``{ - string dirname_forbidden = ":"; + string dirname_forbidden = ":[]"; if (size(name) > 0 && size(name) < 50 && - name == filterchars(name, "-_.:" + String::CAlnum() )) { - if( IP::Check( name)) + name == filterchars(name, "-_.:[]%" + String::CAlnum() )) + { + if( CheckIp( name)) + return true; + if( "" == filterchars( name, dirname_forbidden)) return true; - if( "" != filterchars( name, dirname_forbidden)) - return false; - return true; - } else + Report::Error (sformat(_("The hostname entered is invalid. +Url contains forbidden characters or IP is incorrect. +Use url, IPv4 or IPv6."))); + + return false; + } + else + { // error popup message Report::Error (sformat(_("The hostname entered is invalid. It must be shorter than 50 characters and only use -0-9, A-Z, a-z, dots, -, and _.:"))); +0-9, A-Z, a-z, dots, -, and _.:[]%%"))); + } + return false; }; @@ -216,6 +254,17 @@ and it must begin with a slash (/)."))); } } + /** + * Formats hostname into form suitable for fstab. + * If given param is IPv6 then encloses it into square brackets. + */ + define string FormatHostnameForFstab( string hostname) + { + if( IP::Check6( ParseIpv6( hostname))) + return sformat( regexpmatch( "\\[.*\\]", hostname) ? "%1" : "[%1]", hostname); + return hostname; + } + /** * Check whether pormap is installed, ask user to install it if it is missing * @return boolean true if portmap is installed diff --git a/src/ui.ycp b/src/ui.ycp index a36ddef..9499ae3 100644 --- a/src/ui.ycp +++ b/src/ui.ycp @@ -408,7 +408,7 @@ which probably blocks the network scanning."); } else if (ret == `ok) { - server = (string) UI::QueryWidget(`id(`serverent), `Value); + server = FormatHostnameForFstab( (string) UI::QueryWidget(`id(`serverent), `Value)); pth = StripExtraSlash ((string) UI::QueryWidget(`id(`pathent), `Value)); mount = StripExtraSlash ((string) UI::QueryWidget(`id(`mountent), `Value)); nfs4 = (boolean) UI::QueryWidget(`id(`nfs4), `Value); From 034abca992b711348c2143c146990242918ad50d Mon Sep 17 00:00:00 2001 From: Michal Filka Date: Thu, 20 Sep 2012 14:56:03 +0200 Subject: [PATCH 18/50] Updated testsuite. Added tests for various IPv6 possibilities. --- testsuite/tests/r-check.out | 6 ++++++ testsuite/tests/r-check.ycp | 24 ++++++++++++++++++------ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/testsuite/tests/r-check.out b/testsuite/tests/r-check.out index 0f47c88..5de91c5 100644 --- a/testsuite/tests/r-check.out +++ b/testsuite/tests/r-check.out @@ -17,3 +17,9 @@ Return false Return true Return false Return true +Return false +Return true +Return false +Return true +Return true +Return false diff --git a/testsuite/tests/r-check.ycp b/testsuite/tests/r-check.ycp index b3416aa..83af2bd 100644 --- a/testsuite/tests/r-check.ycp +++ b/testsuite/tests/r-check.ycp @@ -16,12 +16,18 @@ include "testsuite.ycp"; include "nfs/routines.ycp"; - string OK_Name = "foo.bar.com.tw"; - string TooLongName = "123456789012345678901234567890123456789012345678901234567890"; - string IllegalName = "Something:wrong"; - string IPv4 = "192.168.10.1"; - string IPv4_invalid= "192.168.10:1"; - string IPv6 = "fe80::219:d1ff:feac:fd10"; + string OK_Name = "foo.bar.com.tw"; + string TooLongName = "123456789012345678901234567890123456789012345678901234567890"; + string IllegalName = "Something:wrong"; + string IPv4 = "192.168.10.1"; + string IPv4_invalid = "192.168.10:1"; + string IPv6 = "fe80::219:d1ff:feac:fd10"; + string IPv6_invalid = "fe80::219::fd10"; + string IPv6_brackets = "[::1]"; + string IPv6_brackets_invalid = "[::1"; + string IPv6_link_local_nb = "fe80::3%eth0"; + string IPv6_link_local_ib = "[fe80::3%eth0]"; + string IPv6_link_local_invalid = "[fe80::3%]"; DUMP ("check_options"); TEST (``(check_options ("")), [], nil); @@ -45,4 +51,10 @@ TEST (``(CheckHostName (IPv4)), [], nil); TEST (``(CheckHostName (IPv4_invalid)), [], nil); TEST (``(CheckHostName (IPv6)), [], nil); + TEST (``(CheckHostName (IPv6_invalid)), [], nil); + TEST (``(CheckHostName (IPv6_brackets)), [], nil); + TEST (``(CheckHostName (IPv6_brackets_invalid)), [], nil); + TEST (``(CheckHostName (IPv6_link_local_nb)), [], nil); + TEST (``(CheckHostName (IPv6_link_local_ib)), [], nil); + TEST (``(CheckHostName (IPv6_link_local_invalid)), [], nil); } From 2dad9585a21d93e6536f62b33055d37c5db2547a Mon Sep 17 00:00:00 2001 From: Michal Filka Date: Fri, 26 Oct 2012 13:59:38 +0200 Subject: [PATCH 19/50] Updated changelog. Conflicts: VERSION package/yast2-nfs-client.changes Conflicts: package/yast2-nfs-client.changes --- package/yast2-nfs-client.changes | 1 + 1 file changed, 1 insertion(+) diff --git a/package/yast2-nfs-client.changes b/package/yast2-nfs-client.changes index f2e9bd1..b2df4bf 100644 --- a/package/yast2-nfs-client.changes +++ b/package/yast2-nfs-client.changes @@ -3,6 +3,7 @@ Mon Oct 15 08:28:10 UTC 2012 - mfilka@suse.com - ported several old fixes from master branch: - updated testsuite + - added support for IPv6 in square brackets - bnc#719538 - IPv6 addresses supported - bnc#719538 - removed some dead code, whitespaces - autoinstallation fails to enable portmapper/rpcbind service - bnc#744357 From e33aafce8821e9d1958da7c0006a5cdf73da9e29 Mon Sep 17 00:00:00 2001 From: Michal Filka Date: Tue, 25 Sep 2012 13:29:01 +0200 Subject: [PATCH 20/50] Updated testsuite for IPv6 inputs. --- testsuite/tests/r-check.out | 5 +++++ testsuite/tests/r-check.ycp | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/testsuite/tests/r-check.out b/testsuite/tests/r-check.out index 5de91c5..7182678 100644 --- a/testsuite/tests/r-check.out +++ b/testsuite/tests/r-check.out @@ -23,3 +23,8 @@ Return false Return true Return true Return false +Dump FormatHostnameForFstab +Return [::1] +Return [::1] +Return 127.0.0.1 +Return suse.de diff --git a/testsuite/tests/r-check.ycp b/testsuite/tests/r-check.ycp index 83af2bd..38ee5e3 100644 --- a/testsuite/tests/r-check.ycp +++ b/testsuite/tests/r-check.ycp @@ -57,4 +57,10 @@ TEST (``(CheckHostName (IPv6_link_local_nb)), [], nil); TEST (``(CheckHostName (IPv6_link_local_ib)), [], nil); TEST (``(CheckHostName (IPv6_link_local_invalid)), [], nil); + + DUMP ( "FormatHostnameForFstab"); + TEST ( FormatHostnameForFstab( "::1"), [], nil); + TEST ( FormatHostnameForFstab( "[::1]"), [], nil); + TEST ( FormatHostnameForFstab( "127.0.0.1"), [], nil); + TEST ( FormatHostnameForFstab( "suse.de"), [], nil); } From af57a16af28f9c22c1f0cf30d5be12e8d2cf30c9 Mon Sep 17 00:00:00 2001 From: Michal Filka Date: Tue, 25 Sep 2012 13:54:36 +0200 Subject: [PATCH 21/50] Part of IPv6 specific checking moved to yast-yast2. Minor refactoring in CheckHostname. --- src/routines.ycp | 66 ++++++++++++++---------------------------------- 1 file changed, 19 insertions(+), 47 deletions(-) diff --git a/src/routines.ycp b/src/routines.ycp index 8261983..2c64209 100644 --- a/src/routines.ycp +++ b/src/routines.ycp @@ -24,6 +24,7 @@ import "Package"; import "Report"; import "IP"; + import "Hostname"; import "String"; /** @@ -73,35 +74,6 @@ }); } - /** - * If param contains IPv6 in one of its various forms, extracts it. - * - * @param ip a buffer with address - * @return IPv6 part of ip param, unchanged ip param otherwise - */ - define string ParseIpv6( string ip) - { - // if ip is closed in [ ] or contain % then it can be special case of IPv6 syntax, - // so extract ipv6 (see description later) and continue with check. - // - // IPv6 syntax: - // - pure ipv6 blob (e.g. f008::1) - // - ipv6 blob with link local suffix (e.g. f008::1%eth0) - // - dtto in square brackets (e.g. [f008::1%eth0] ) - if( regexpmatch( ip, "^\\[.*\\]") || regexpmatch( ip, "^[^][%]+(%[^][%]+){0,1}$")) - ip = regexpsub( ip, "^\\[?([^][%]+)(%[^][%]+){0,1}(\\]|$)", "\\1"); - - return ip; - } - - /** - * Checks if given entry is valid ip address - */ - define boolean CheckIp( string ip) - { - return IP::Check( ParseIpv6( ip) ); - } - /** * Check for the validity of a hostname: nonempty, shorter than 50 chars, * [-A-Za-z._]. If invalid, a message is displayed. @@ -109,30 +81,28 @@ * @return whether valid */ define boolean CheckHostName(string name) ``{ - string dirname_forbidden = ":[]"; + + y2milestone( "CheckHostName: hostname=%1", name); if (size(name) > 0 && - size(name) < 50 && - name == filterchars(name, "-_.:[]%" + String::CAlnum() )) + size(name) < 50) { - if( CheckIp( name)) + if( IP::Check4( name)) + return true; + if( IP::Check6( IP::UndecorateIPv6( name))) return true; - if( "" == filterchars( name, dirname_forbidden)) + if( Hostname::CheckDomain( name)) return true; + } - Report::Error (sformat(_("The hostname entered is invalid. -Url contains forbidden characters or IP is incorrect. -Use url, IPv4 or IPv6."))); + // error popup message - return false; - } - else - { - // error popup message - Report::Error (sformat(_("The hostname entered is invalid. It must be + Report::Error ( sformat(_("The hostname entered is invalid. It must be shorter than 50 characters and only use -0-9, A-Z, a-z, dots, -, and _.:[]%%"))); - } +valid IPv4, IPv6 or domain name. +Valid IPv4: %1 +Valid IPv6: %2 +Valid domain: %3"), IP::Valid4(), IP::Valid6(), Hostname::ValidDomain()) ); return false; }; @@ -260,8 +230,10 @@ and it must begin with a slash (/)."))); */ define string FormatHostnameForFstab( string hostname) { - if( IP::Check6( ParseIpv6( hostname))) - return sformat( regexpmatch( "\\[.*\\]", hostname) ? "%1" : "[%1]", hostname); + y2milestone( "FormatHostnameForFstab: hostname=%1", hostname); + + if( IP::Check6( IP::UndecorateIPv6( hostname))) + return sformat( regexpmatch( hostname, "\\[.*\\]") ? "%1" : "[%1]", hostname); return hostname; } From 77395a15bc51457e052b2a4dea03e775400ffc4e Mon Sep 17 00:00:00 2001 From: Michal Filka Date: Mon, 1 Oct 2012 08:55:37 +0200 Subject: [PATCH 22/50] Updated spec file. Conflicts: yast2-nfs-client.spec.in --- yast2-nfs-client.spec.in | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/yast2-nfs-client.spec.in b/yast2-nfs-client.spec.in index 89e5d4f..7a995cc 100644 --- a/yast2-nfs-client.spec.in +++ b/yast2-nfs-client.spec.in @@ -3,7 +3,9 @@ @HEADER@ BuildRequires: perl-XML-Writer update-desktop-files yast2 yast2-devtools yast2-testsuite #ag_showexports moved to yast2 base -Requires: yast2 >= 2.17.40 +# yast2 2.17.121 introduces extended IPv6 support. +Requires: yast2 >= 2.17.121 +BuildRequires: yast2 >= 2.17.121 #idmapd_conf agent Requires: yast2-nfs-common # showmount, #150382, #286300 From d5381a24cbfb659b631fb5fbdf2ffdf9ac4618e8 Mon Sep 17 00:00:00 2001 From: Martin Vidner Date: Fri, 16 Nov 2012 11:31:38 +0100 Subject: [PATCH 23/50] enable compiling, testing, packaging from the WC (bnc#790490) by mimicking the runtime directory layout --- doc/autodocs/Makefile.am | 2 ++ src/Makefile.am | 29 +++++++++++---------------- src/{ => clients}/nfs-client.ycp | 0 src/{ => clients}/nfs-client4part.ycp | 0 src/{ => clients}/nfs.ycp | 0 src/{ => clients}/nfs_auto.ycp | 0 src/{ => include/nfs}/routines.ycp | 0 src/{ => include/nfs}/ui.ycp | 0 src/{ => include/nfs}/wizards.ycp | 0 src/{ => modules}/Nfs.ycp | 0 testsuite/Makefile.am | 5 +++-- 11 files changed, 17 insertions(+), 19 deletions(-) rename src/{ => clients}/nfs-client.ycp (100%) rename src/{ => clients}/nfs-client4part.ycp (100%) rename src/{ => clients}/nfs.ycp (100%) rename src/{ => clients}/nfs_auto.ycp (100%) rename src/{ => include/nfs}/routines.ycp (100%) rename src/{ => include/nfs}/ui.ycp (100%) rename src/{ => include/nfs}/wizards.ycp (100%) rename src/{ => modules}/Nfs.ycp (100%) diff --git a/doc/autodocs/Makefile.am b/doc/autodocs/Makefile.am index 2a6f678..e883f62 100644 --- a/doc/autodocs/Makefile.am +++ b/doc/autodocs/Makefile.am @@ -1,3 +1,5 @@ # Makefile.am for YCP module .../doc/autodocs +AUTODOCS_YCP = $(wildcard $(top_srcdir)/src/*/*.ycp $(top_srcdir)/src/*/*/*.ycp) +AUTODOCS_STRIP = $(top_srcdir)/src include $(top_srcdir)/autodocs-ycp.ami diff --git a/src/Makefile.am b/src/Makefile.am index ea0dbee..707a6cb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,32 +2,27 @@ myincludedir = @yncludedir@/nfs -client_DATA = \ - nfs_auto.ycp \ - nfs-client.ycp \ - nfs-client4part.ycp \ - nfs.ycp +YCPC_Y2DIR = . -myinclude_DATA = \ - routines.ycp \ - ui.ycp \ - wizards.ycp +client_DATA = \ + clients/nfs_auto.ycp \ + clients/nfs-client.ycp \ + clients/nfs-client4part.ycp \ + clients/nfs.ycp + +myinclude_DATA = \ + include/nfs/routines.ycp \ + include/nfs/ui.ycp \ + include/nfs/wizards.ycp module_DATA = \ - Nfs.ycp + modules/Nfs.ycp desktop_DATA = nfs.desktop rncdir = $(schemadir)/autoyast/rnc rnc_DATA = nfs.rnc -nfs: - ln -sf . nfs - -ycpchook = nfs - -YCPCFLAGS = -I. - EXTRA_DIST = $(client_DATA) $(myinclude_DATA) $(module_DATA) $(desktop_DATA) $(rnc_DATA) include $(top_srcdir)/Makefile.am.common diff --git a/src/nfs-client.ycp b/src/clients/nfs-client.ycp similarity index 100% rename from src/nfs-client.ycp rename to src/clients/nfs-client.ycp diff --git a/src/nfs-client4part.ycp b/src/clients/nfs-client4part.ycp similarity index 100% rename from src/nfs-client4part.ycp rename to src/clients/nfs-client4part.ycp diff --git a/src/nfs.ycp b/src/clients/nfs.ycp similarity index 100% rename from src/nfs.ycp rename to src/clients/nfs.ycp diff --git a/src/nfs_auto.ycp b/src/clients/nfs_auto.ycp similarity index 100% rename from src/nfs_auto.ycp rename to src/clients/nfs_auto.ycp diff --git a/src/routines.ycp b/src/include/nfs/routines.ycp similarity index 100% rename from src/routines.ycp rename to src/include/nfs/routines.ycp diff --git a/src/ui.ycp b/src/include/nfs/ui.ycp similarity index 100% rename from src/ui.ycp rename to src/include/nfs/ui.ycp diff --git a/src/wizards.ycp b/src/include/nfs/wizards.ycp similarity index 100% rename from src/wizards.ycp rename to src/include/nfs/wizards.ycp diff --git a/src/Nfs.ycp b/src/modules/Nfs.ycp similarity index 100% rename from src/Nfs.ycp rename to src/modules/Nfs.ycp diff --git a/testsuite/Makefile.am b/testsuite/Makefile.am index d9b12b0..3a56c02 100644 --- a/testsuite/Makefile.am +++ b/testsuite/Makefile.am @@ -1,8 +1,9 @@ # # Makefile.am for .../testsuite # -# Do not edit this file (Makefile.am) as it will be overwritten! -# + +# enable make check in the working copy +export Y2DIR = $(top_srcdir)/src AUTOMAKE_OPTIONS = dejagnu EXTRA_DIST = $(wildcard tests/*.out) $(wildcard tests/*.err) $(wildcard tests/*.ycp) $(wildcard tests/*.yh) From 3c50e4d750240e705681a804116636e8fbbbfa98 Mon Sep 17 00:00:00 2001 From: Martin Vidner Date: Fri, 16 Nov 2012 11:33:35 +0100 Subject: [PATCH 24/50] removed an unused directory --- agents/.cvsignore | 2 -- agents/Makefile.am | 5 ----- 2 files changed, 7 deletions(-) delete mode 100644 agents/.cvsignore delete mode 100644 agents/Makefile.am diff --git a/agents/.cvsignore b/agents/.cvsignore deleted file mode 100644 index 282522d..0000000 --- a/agents/.cvsignore +++ /dev/null @@ -1,2 +0,0 @@ -Makefile -Makefile.in diff --git a/agents/Makefile.am b/agents/Makefile.am deleted file mode 100644 index dec8b7c..0000000 --- a/agents/Makefile.am +++ /dev/null @@ -1,5 +0,0 @@ -# -# Makefile.am for nfs-client/agents -# -# $Id$ -# From dd3d4199ccdeeab2d0d1cb53db12c011877bfb0c Mon Sep 17 00:00:00 2001 From: Martin Vidner Date: Fri, 16 Nov 2012 11:36:49 +0100 Subject: [PATCH 25/50] gitignore --- .cvsignore | 24 ------------------------ .gitignore | 19 +++++++++++++++++++ doc/.cvsignore | 2 -- doc/autodocs/.cvsignore | 3 --- package/.cvsignore | 2 -- src/.cvsignore | 4 ---- testsuite/.cvsignore | 11 ----------- testsuite/.gitignore | 12 ++++++++++++ 8 files changed, 31 insertions(+), 46 deletions(-) delete mode 100644 .cvsignore create mode 100644 .gitignore delete mode 100644 doc/.cvsignore delete mode 100644 doc/autodocs/.cvsignore delete mode 100644 package/.cvsignore delete mode 100644 src/.cvsignore delete mode 100644 testsuite/.cvsignore create mode 100644 testsuite/.gitignore diff --git a/.cvsignore b/.cvsignore deleted file mode 100644 index f26f7e8..0000000 --- a/.cvsignore +++ /dev/null @@ -1,24 +0,0 @@ -Makefile -Makefile.am -Makefile.in -aclocal.m4 -autom4te.cache -config.cache -config.guess -config.h -config.h.in -config.log -config.status -config.sub -configure -configure.in -depcomp -install-sh -libtool -ltconfig -ltmain.sh -missing -mkinstalldirs -stamp-h* -*.pot -Makefile.am.common diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..aab5d58 --- /dev/null +++ b/.gitignore @@ -0,0 +1,19 @@ +# autotools +Makefile +Makefile.in +aclocal.m4 +autom4te.cache/ +config.guess +config.log +config.status +config.sub +configure +install-sh +missing +# devtools +.dep +*.ami +/Makefile.am +/Makefile.am.common +configure.in +doc/autodocs/*.html diff --git a/doc/.cvsignore b/doc/.cvsignore deleted file mode 100644 index 282522d..0000000 --- a/doc/.cvsignore +++ /dev/null @@ -1,2 +0,0 @@ -Makefile -Makefile.in diff --git a/doc/autodocs/.cvsignore b/doc/autodocs/.cvsignore deleted file mode 100644 index 2f083ef..0000000 --- a/doc/autodocs/.cvsignore +++ /dev/null @@ -1,3 +0,0 @@ -Makefile -Makefile.in -*.html diff --git a/package/.cvsignore b/package/.cvsignore deleted file mode 100644 index 65d0b1a..0000000 --- a/package/.cvsignore +++ /dev/null @@ -1,2 +0,0 @@ -*.spec -*.bz2 diff --git a/src/.cvsignore b/src/.cvsignore deleted file mode 100644 index 31486da..0000000 --- a/src/.cvsignore +++ /dev/null @@ -1,4 +0,0 @@ -Makefile -Makefile.in -.dep -*.ybc diff --git a/testsuite/.cvsignore b/testsuite/.cvsignore deleted file mode 100644 index 24f1e26..0000000 --- a/testsuite/.cvsignore +++ /dev/null @@ -1,11 +0,0 @@ -Makefile -Makefile.in -site.exp -*.sum -*.log -tmp.out* -tmp.err* -tmp.log* -config -run -*.test diff --git a/testsuite/.gitignore b/testsuite/.gitignore new file mode 100644 index 0000000..30f97be --- /dev/null +++ b/testsuite/.gitignore @@ -0,0 +1,12 @@ +# dejagnu +site.exp +# * is the rpm name +*.log +*.sum +*.test/ +# * are test cases +tmp.out* +tmp.err* +# harness +config/ +run/ From e73e82d225c1f3f60b67ce8905d95c9e74abec5c Mon Sep 17 00:00:00 2001 From: Martin Vidner Date: Fri, 14 Dec 2012 10:37:29 +0100 Subject: [PATCH 26/50] VERSION + .changes --- VERSION | 2 +- package/yast2-nfs-client.changes | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 1f085b8..8e9d016 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.17.14 +2.17.15 diff --git a/package/yast2-nfs-client.changes b/package/yast2-nfs-client.changes index b2df4bf..00808c2 100644 --- a/package/yast2-nfs-client.changes +++ b/package/yast2-nfs-client.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Fri Dec 14 10:35:14 CET 2012 - mvidner@suse.cz + +- enable compiling, testing, packaging from the WC (bnc#790490) +- 2.17.15 + ------------------------------------------------------------------- Mon Oct 15 08:28:10 UTC 2012 - mfilka@suse.com From 2a4e799f30b9a6c5e742c86c43a71e0b04b290b6 Mon Sep 17 00:00:00 2001 From: Martin Vidner Date: Mon, 26 Nov 2012 15:52:04 +0100 Subject: [PATCH 27/50] Factored out backends of probing pop-ups from GetFstabEntry. doc typo: the correct key is "mntops" --- src/include/nfs/ui.ycp | 45 ++---------------------------- src/modules/Nfs.ycp | 62 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 63 insertions(+), 44 deletions(-) diff --git a/src/include/nfs/ui.ycp b/src/include/nfs/ui.ycp index 9499ae3..a332468 100644 --- a/src/include/nfs/ui.ycp +++ b/src/include/nfs/ui.ycp @@ -298,26 +298,10 @@ { if (hosts == nil) { - //newer, shinier, better rpcinfo from rpcbind (#450056) - string prog_name = "/sbin/rpcinfo"; - string delim = ""; - - //fallback from glibc (uses different field separators, grr :( ) - if( !FileUtils::Exists(prog_name) ) - { - prog_name = "/usr/sbin/rpcinfo"; - delim = "-d ' ' "; - } - // label message UI::OpenDialog(`Label(_("Scanning for hosts on this LAN..."))); - // #71064 - // this works also if ICMP broadcasts are ignored - string cmd = prog_name + " -b mountd 1 | cut " + delim + "-f 2 | sort -u"; - map out = (map) SCR::Execute (.target.bash_output, cmd); - hosts = filter (string s, splitstring (out["stdout"]:"", "\n"), ``( s != "")); + hosts = Nfs::ProbeServers(); UI::CloseDialog(); - } if( hosts == [] || hosts == nil ) { @@ -358,32 +342,9 @@ which probably blocks the network scanning."); sformat (_("Getting directory list for \"%1\"..."), server) )); - list dirs = []; - - // showmounts does not work for nfsv4 (#466454) - if (v4) - { - string tmpdir = Nfs::Mount(server, "/", nil, "ro", "nfs4"); - - // This is completely stupid way how to explore what can be mounted - // and I even don't know if it is correct. Maybe 'find tmpdir -xdev -type d' - // should be used instead. No clue :( - dirs = maplist( string dirent, (list ) SCR::Read(.target.dir, tmpdir), { - return "/" + dirent; - }); - dirs = prepend(dirs, "/"); - Nfs::Unmount( tmpdir ); - } - else - { - dirs = (list) SCR::Read (.net.showexports, server); - } - - if (dirs == nil) - { - dirs = ["internal error"]; - } + list dirs = Nfs::ProbeExports (server, v4); UI::CloseDialog (); + string dir = ChooseExport (dirs); if (dir != nil) { diff --git a/src/modules/Nfs.ycp b/src/modules/Nfs.ycp index 995820c..912e34c 100644 --- a/src/modules/Nfs.ycp +++ b/src/modules/Nfs.ycp @@ -21,7 +21,8 @@ textdomain "nfs"; - import "Mode";; + import "FileUtils"; + import "Mode"; import "Report"; import "Service"; import "Summary"; @@ -63,7 +64,7 @@ global list required_packages = [ "nfs-client" ]; /** - * eg.: [ $["spec": "moon:/cheese", file: "/mooncheese", "mntopts": "defaults"], ...] + * eg.: [ $["spec": "moon:/cheese", file: "/mooncheese", "mntops": "defaults"], ...] */ global list > nfs_entries = []; @@ -614,7 +615,64 @@ the NFS client configuration.\n")); } + /** + * Probe the LAN for NFS servers. + * Uses RPC broadcast to mountd. + * @return a list of hostnames + */ + global define list ProbeServers() { + //newer, shinier, better rpcinfo from rpcbind (#450056) + string prog_name = "/sbin/rpcinfo"; + string delim = ""; + + //fallback from glibc (uses different field separators, grr :( ) + if( !FileUtils::Exists(prog_name) ) + { + prog_name = "/usr/sbin/rpcinfo"; + delim = "-d ' ' "; + } + // #71064 + // this works also if ICMP broadcasts are ignored + string cmd = prog_name + " -b mountd 1 | cut " + delim + "-f 2 | sort -u"; + map out = (map) SCR::Execute (.target.bash_output, cmd); + list hosts = filter (string s, splitstring (out["stdout"]:"", "\n"), ``( s != "")); + return hosts; + } + /** + * Probe a server for its exports. + * @param server IP or hostname + * @param v4 Use NFSv4? + * @return a list of exported paths + */ + global list ProbeExports(string server, boolean v4) { + list dirs = []; + + // showmounts does not work for nfsv4 (#466454) + if (v4) + { + string tmpdir = Mount(server, "/", nil, "ro", "nfs4"); + + // This is completely stupid way how to explore what can be mounted + // and I even don't know if it is correct. Maybe 'find tmpdir -xdev -type d' + // should be used instead. No clue :( + dirs = maplist( string dirent, (list ) SCR::Read(.target.dir, tmpdir), { + return "/" + dirent; + }); + dirs = prepend(dirs, "/"); + Unmount( tmpdir ); + } + else + { + dirs = (list) SCR::Read (.net.showexports, server); + } + + if (dirs == nil) + { + dirs = ["internal error"]; + } + return dirs; + } } From 3354f0c064900dd5e3c93846699058d77c8af8bd Mon Sep 17 00:00:00 2001 From: Martin Vidner Date: Mon, 26 Nov 2012 15:53:15 +0100 Subject: [PATCH 28/50] renamed check_options to Nfs::Options::validate --- src/Makefile.am | 13 ++++++- src/clients/nfs.ycp | 5 ++- src/include/nfs/routines.ycp | 58 ----------------------------- src/include/nfs/ui.ycp | 3 +- src/modules/Nfs.ycp | 3 +- src/modules/Nfs/Options.ycp | 66 +++++++++++++++++++++++++++++++++ testsuite/tests/nfs-options.err | 0 testsuite/tests/nfs-options.out | 11 ++++++ testsuite/tests/nfs-options.ycp | 16 ++++++++ testsuite/tests/r-check.out | 11 ------ testsuite/tests/r-check.ycp | 12 ------ yast2-nfs-client.spec.in | 3 ++ 12 files changed, 115 insertions(+), 86 deletions(-) create mode 100644 src/modules/Nfs/Options.ycp create mode 100644 testsuite/tests/nfs-options.err create mode 100644 testsuite/tests/nfs-options.out create mode 100644 testsuite/tests/nfs-options.ycp diff --git a/src/Makefile.am b/src/Makefile.am index 707a6cb..335b9a7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -18,11 +18,22 @@ myinclude_DATA = \ module_DATA = \ modules/Nfs.ycp +nfs_moduledir = @moduledir@/Nfs +nfs_module_DATA = \ + modules/Nfs/Options.ycp + +nfs_modulebindir = $(nfs_moduledir) +nfs_modulebin_DATA = $(patsubst %.ycp,%.ybc,$(nfs_module_DATA)) + +# .dep does not work with subdirs +modules/Nfs.ybc: modules/Nfs/Options.ybc + desktop_DATA = nfs.desktop rncdir = $(schemadir)/autoyast/rnc rnc_DATA = nfs.rnc -EXTRA_DIST = $(client_DATA) $(myinclude_DATA) $(module_DATA) $(desktop_DATA) $(rnc_DATA) +EXTRA_DIST = $(client_DATA) $(myinclude_DATA) $(module_DATA) $(nfs_module_DATA) $(desktop_DATA) $(rnc_DATA) include $(top_srcdir)/Makefile.am.common +ybcfiles += $(filter %.ybc,$(nfs_modulebin_DATA)) diff --git a/src/clients/nfs.ycp b/src/clients/nfs.ycp index 58aebbe..3eaccca 100644 --- a/src/clients/nfs.ycp +++ b/src/clients/nfs.ycp @@ -25,6 +25,7 @@ y2milestone ("----------------------------------------"); y2milestone ("NFS module started"); import "Nfs"; +import "Nfs::Options"; import "Progress"; import "Report"; import "String"; @@ -86,7 +87,7 @@ boolean NfsAddHandler (map options) { if (! haskey (options, "mntops")) options["mntops"] = "defaults"; - string options_error = check_options (options["mntops"]:""); + string options_error = Nfs::Options::validate (options["mntops"]:""); if (size (options_error) > 0) { Report::Error (options_error); @@ -184,7 +185,7 @@ boolean NfsEditHandler (map options) { !CheckPath (mount) || IsMpInFstab (existing, mount)) return false; - string options_error = check_options (entry["mntops"]:""); + string options_error = Nfs::Options::validate (entry["mntops"]:""); if (size (options_error) > 0) { Report::Error (options_error); diff --git a/src/include/nfs/routines.ycp b/src/include/nfs/routines.ycp index 2c64209..a24ef8a 100644 --- a/src/include/nfs/routines.ycp +++ b/src/include/nfs/routines.ycp @@ -149,64 +149,6 @@ and it must begin with a slash (/)."))); return false; }; - /** - * Checks the nfs options for /etc/fstab: - * nonempty, comma separated list of foo,nofoo,bar=baz (see nfs(5)) - * @param options options - * @return a translated string with error message, emtpy string if ok - */ - define string check_options (string options) ``{ - - // To translators: error popup - if (size (options) == 0) return _("Empty option strings are not allowed."); - if (options == "defaults") return ""; - - - list option_list = splitstring (options, ","); - -//the options must be easy to sync with mount.c and nfsmount.c - - // these can be negated by "no" - list non_value = ["bg", "fg", "soft", "hard", "intr", "posix", "cto", "ac", "acl", - "lock", "tcp", "udp", "rdirplus", - // these are common for all fs types - "atime", "auto", "dev", "exec", "group", "owner", - "suid", "user", "users"]; - // these cannot be negated - // they are not nfs specific BTW - list non_value1 = ["defaults", "async", "sync", "dirsync", "ro", "rw", - "remount", "bind", "rbind", "_netdev", ]; - list with_value = ["rsize", "wsize", "timeo", "retrans", "acregmin", "acregmax", - "acdirmin", "acdirmin", "acdirmax", "actimeo", "retry", "namlen", - "port", "proto", "clientaddr", "mountport", "mounthost", - "mountprog", "mountvers", "nfsprog", "nfsvers", "vers", "sec" ]; - integer i = 0; - string current_option = ""; - - // first fiter out non value options and its nooptions forms (see nfs(5)) - option_list = filter (string e, option_list, ``(!contains (non_value, e))); - non_value = maplist (string e, non_value, ``(sformat ("no%1", e))); - option_list = filter (string e, option_list, ``(!contains (non_value, e))); - option_list = filter (string e, option_list, ``(!contains (non_value1, e))); - - while (i < size (option_list)) - { - string opt = option_list[i]:""; - list value = splitstring (opt, "="); - string v0 = value[0]:""; - string v1 = value[1]:""; - // FIXME: this also triggers for "intr=bogus" - // To translators: error popup - if (!contains (with_value, v0)) return sformat (_("Unknown option: %1"), v0); - // To translators: error popup - if (size (value) != 2) return sformat (_("Invalid option: %1"), opt); - // To translators: error popup - if (v1 == "") return sformat (_("Empty value for option: %1"), v0); - i = i + 1; - } - - return ""; - } /** * Strips a superfluous slash off the end of a pathname. diff --git a/src/include/nfs/ui.ycp b/src/include/nfs/ui.ycp index a332468..ce604d1 100644 --- a/src/include/nfs/ui.ycp +++ b/src/include/nfs/ui.ycp @@ -27,6 +27,7 @@ import "FileUtils"; import "Label"; import "Nfs"; + import "Nfs::Options"; import "Popup"; import "SuSEFirewall"; import "Wizard"; @@ -376,7 +377,7 @@ which probably blocks the network scanning."); options = deletechars ((string) UI::QueryWidget(`id(`optionsent), `Value), " "); ret = nil; - string options_error = check_options (options); + string options_error = Nfs::Options::validate (options); if (!CheckHostName (server)) { UI::SetFocus (`id (`serverent)); diff --git a/src/modules/Nfs.ycp b/src/modules/Nfs.ycp index 912e34c..e540433 100644 --- a/src/modules/Nfs.ycp +++ b/src/modules/Nfs.ycp @@ -23,6 +23,7 @@ import "FileUtils"; import "Mode"; + import "Nfs::Options"; import "Report"; import "Service"; import "Summary"; @@ -477,7 +478,7 @@ the NFS client configuration.\n")); // check if options are valid if (size(options) > 0) { - if (check_options(options) != "") + if (Nfs::Options::validate(options) != "") { y2warning("invalid mount options: %1", options); return nil; diff --git a/src/modules/Nfs/Options.ycp b/src/modules/Nfs/Options.ycp new file mode 100644 index 0000000..553834d --- /dev/null +++ b/src/modules/Nfs/Options.ycp @@ -0,0 +1,66 @@ +{ + +module "Nfs::Options"; +textdomain "nfs"; + +/** + * Checks the nfs options for /etc/fstab: + * nonempty, comma separated list of foo,nofoo,bar=baz (see nfs(5)) + * @param options options + * @return a translated string with error message, emtpy string if ok + */ +global define string validate (string options) { + // To translators: error popup + if (size (options) == 0) return _("Empty option strings are not allowed."); + if (options == "defaults") return ""; + + + list option_list = splitstring (options, ","); + + //the options must be easy to sync with mount.c and nfsmount.c + + // these can be negated by "no" + list non_value = ["bg", "fg", "soft", "hard", "intr", "posix", "cto", "ac", "acl", + "lock", "tcp", "udp", "rdirplus", + // these are common for all fs types + "atime", "auto", "dev", "exec", "group", "owner", + "suid", "user", "users"]; + // these cannot be negated + // they are not nfs specific BTW + list non_value1 = ["defaults", "async", "sync", "dirsync", "ro", "rw", + "remount", "bind", "rbind", "_netdev", ]; + list with_value = ["rsize", "wsize", "timeo", "retrans", "acregmin", "acregmax", + "acdirmin", "acdirmin", "acdirmax", "actimeo", "retry", "namlen", + "port", "proto", "clientaddr", "mountport", "mounthost", + "mountprog", "mountvers", "nfsprog", "nfsvers", "vers", + "sec" ]; + integer i = 0; + string current_option = ""; + + // first fiter out non value options and its nooptions forms (see nfs(5)) + option_list = filter (string e, option_list, ``(!contains (non_value, e))); + non_value = maplist (string e, non_value, ``(sformat ("no%1", e))); + option_list = filter (string e, option_list, ``(!contains (non_value, e))); + option_list = filter (string e, option_list, ``(!contains (non_value1, e))); + + while (i < size (option_list)) + { + string opt = option_list[i]:""; + list value = splitstring (opt, "="); + string v0 = value[0]:""; + string v1 = value[1]:""; + // FIXME: this also triggers for "intr=bogus" + // To translators: error popup + if (!contains (with_value, v0)) return sformat (_("Unknown option: %1"), v0); + // To translators: error popup + if (size (value) != 2) return sformat (_("Invalid option: %1"), opt); + // To translators: error popup + if (v1 == "") return sformat (_("Empty value for option: %1"), v0); + i = i + 1; + } + + return ""; +} + +/*EOF*/ +} diff --git a/testsuite/tests/nfs-options.err b/testsuite/tests/nfs-options.err new file mode 100644 index 0000000..e69de29 diff --git a/testsuite/tests/nfs-options.out b/testsuite/tests/nfs-options.out new file mode 100644 index 0000000..4ccf1aa --- /dev/null +++ b/testsuite/tests/nfs-options.out @@ -0,0 +1,11 @@ +Dump Nfs::Options::validate +Return Empty option strings are not allowed. +Return +Return +Return +Return +Return Unknown option: bg +Return Unknown option: unknownoption +Return Unknown option: unknownassignment +Return Empty value for option: rsize +Return Unknown option: two diff --git a/testsuite/tests/nfs-options.ycp b/testsuite/tests/nfs-options.ycp new file mode 100644 index 0000000..a5ad6b0 --- /dev/null +++ b/testsuite/tests/nfs-options.ycp @@ -0,0 +1,16 @@ +{ + include "testsuite.ycp"; + import "Nfs::Options"; + + DUMP ("Nfs::Options::validate"); + TEST (``(Nfs::Options::validate ("")), [], nil); + TEST (``(Nfs::Options::validate ("defaults")), [], nil); + TEST (``(Nfs::Options::validate ("nolock,bg")), [], nil); + TEST (``(Nfs::Options::validate ("nolock,nobg")), [], nil); + TEST (``(Nfs::Options::validate ("nolock,rsize=8192")), [], nil); + TEST (``(Nfs::Options::validate ("nolock, bg")), [], nil); + TEST (``(Nfs::Options::validate ("nolock,unknownoption")), [], nil); + TEST (``(Nfs::Options::validate ("nolock,unknownassignment=true")), [], nil); + TEST (``(Nfs::Options::validate ("nolock,rsize=")), [], nil); + TEST (``(Nfs::Options::validate ("nolock,two=equal=signs")), [], nil); +} diff --git a/testsuite/tests/r-check.out b/testsuite/tests/r-check.out index 7182678..a5f55b3 100644 --- a/testsuite/tests/r-check.out +++ b/testsuite/tests/r-check.out @@ -1,14 +1,3 @@ -Dump check_options -Return Empty option strings are not allowed. -Return -Return -Return -Return -Return Unknown option: bg -Return Unknown option: unknownoption -Return Unknown option: unknownassignment -Return Empty value for option: rsize -Return Unknown option: two Dump CheckHostName Return true Return false diff --git a/testsuite/tests/r-check.ycp b/testsuite/tests/r-check.ycp index 38ee5e3..fcc53c4 100644 --- a/testsuite/tests/r-check.ycp +++ b/testsuite/tests/r-check.ycp @@ -29,18 +29,6 @@ string IPv6_link_local_ib = "[fe80::3%eth0]"; string IPv6_link_local_invalid = "[fe80::3%]"; - DUMP ("check_options"); - TEST (``(check_options ("")), [], nil); - TEST (``(check_options ("defaults")), [], nil); - TEST (``(check_options ("nolock,bg")), [], nil); - TEST (``(check_options ("nolock,nobg")), [], nil); - TEST (``(check_options ("nolock,rsize=8192")), [], nil); - TEST (``(check_options ("nolock, bg")), [], nil); - TEST (``(check_options ("nolock,unknownoption")), [], nil); - TEST (``(check_options ("nolock,unknownassignment=true")), [], nil); - TEST (``(check_options ("nolock,rsize=")), [], nil); - TEST (``(check_options ("nolock,two=equal=signs")), [], nil); - DUMP ("CheckHostName"); TEST (``(CheckHostName (OK_Name)), [], nil); TEST (``(CheckHostName (TooLongName)), [], nil); diff --git a/yast2-nfs-client.spec.in b/yast2-nfs-client.spec.in index 7a995cc..7dd7ac3 100644 --- a/yast2-nfs-client.spec.in +++ b/yast2-nfs-client.spec.in @@ -44,6 +44,9 @@ Summary: Configuration of nfs %dir @moduledir@ @moduledir@/Nfs.ycp @moduledir@/Nfs.ybc +%dir @moduledir@/Nfs +@moduledir@/Nfs/Options.ycp +@moduledir@/Nfs/Options.ybc %dir @desktopdir@ @desktopdir@/nfs.desktop %doc @docdir@ From 1c9eee734d87848072571f4faf0bdd6cf69fda32 Mon Sep 17 00:00:00 2001 From: Martin Vidner Date: Mon, 26 Nov 2012 14:58:37 +0100 Subject: [PATCH 29/50] Added minorvers=1 for pNFS (FATE#312259). factored out Nfs::Options::{get_nfs41,set_nfs41} --- src/include/nfs/ui.ycp | 13 +++++++- src/modules/Nfs/Options.ycp | 40 +++++++++++++++++++++++- testsuite/tests/nfs-options.out | 2 ++ testsuite/tests/nfs-options.ycp | 55 +++++++++++++++++++++++++++++++++ 4 files changed, 108 insertions(+), 2 deletions(-) diff --git a/src/include/nfs/ui.ycp b/src/include/nfs/ui.ycp index ce604d1..dd21230 100644 --- a/src/include/nfs/ui.ycp +++ b/src/include/nfs/ui.ycp @@ -198,6 +198,7 @@ string pth = ""; string mount = ""; boolean nfs4 = false; + boolean nfs41 = false; string options = "defaults"; list servers = [ ]; string old = ""; @@ -210,6 +211,7 @@ mount = fstab_ent["file"]:""; nfs4 = fstab_ent["vfstype"]:"" == "nfs4"; options = fstab_ent["mntops"]:""; + nfs41 = nfs4 && Nfs::Options::get_nfs41 (options); servers = [ server ]; old = fstab_ent["spec"]:""; } @@ -263,7 +265,14 @@ `PushButton (`id (`pathent_list), _("&Select")) ) ), - `Left( `CheckBox(`id(`nfs4), _("NFS&v4 Share"), nfs4)), + `Left( + `HBox( + `CheckBox(`id(`nfs4), _("NFS&v4 Share"), nfs4), + `HSpacing(2), + // parallel NFS, protocol version 4.1 + `CheckBox(`id(`nfs41), _("pNFS (v4.1)"), nfs41) + ) + ), `Left( TextAndButton ( `InputField(`id(`mountent), @@ -374,7 +383,9 @@ which probably blocks the network scanning."); pth = StripExtraSlash ((string) UI::QueryWidget(`id(`pathent), `Value)); mount = StripExtraSlash ((string) UI::QueryWidget(`id(`mountent), `Value)); nfs4 = (boolean) UI::QueryWidget(`id(`nfs4), `Value); + nfs41 = (boolean) UI::QueryWidget(`id(`nfs41), `Value); options = deletechars ((string) UI::QueryWidget(`id(`optionsent), `Value), " "); + options = Nfs::Options::set_nfs41(options, nfs41); ret = nil; string options_error = Nfs::Options::validate (options); diff --git a/src/modules/Nfs/Options.ycp b/src/modules/Nfs/Options.ycp index 553834d..d8dccb6 100644 --- a/src/modules/Nfs/Options.ycp +++ b/src/modules/Nfs/Options.ycp @@ -32,7 +32,7 @@ global define string validate (string options) { list with_value = ["rsize", "wsize", "timeo", "retrans", "acregmin", "acregmax", "acdirmin", "acdirmin", "acdirmax", "actimeo", "retry", "namlen", "port", "proto", "clientaddr", "mountport", "mounthost", - "mountprog", "mountvers", "nfsprog", "nfsvers", "vers", + "mountprog", "mountvers", "nfsprog", "nfsvers", "vers", "minorversion", "sec" ]; integer i = 0; string current_option = ""; @@ -62,5 +62,43 @@ global define string validate (string options) { return ""; } +/** +FIXME: factor out get_nfs4(vfstype, options) (depending on n::o)! + * @return is version >= 4.1 enabled + */ +global boolean get_nfs41(string options) { + list option_list = splitstring (options, ","); + + return contains(option_list, "minorversion=1"); +} + +/** + * Add or remove minorversion=1 according to nfs41. + * FIXME vfstype=nfs4 is deprecated in favor of nfsvers=4 (aka vers=4) + */ +global define string set_nfs41(string options, boolean nfs41) { + // don't mutate the string unnecessarily + if (get_nfs41(options) == nfs41) { + return options; + } + + const string OPT = "minorversion=1"; + const string CLEAN = "minorversion=0"; + + if (options == "defaults") { options = ""; } + list option_list = splitstring(options, ","); + option_list = filter(string opt, option_list, ``( opt != OPT )); + option_list = filter(string opt, option_list, ``( opt != CLEAN )); + + if (nfs41) { + option_list = add(option_list, OPT); + } + + options = mergestring(option_list, ","); + if (options == "") { options = "defaults"; } + + return options; +} + /*EOF*/ } diff --git a/testsuite/tests/nfs-options.out b/testsuite/tests/nfs-options.out index 4ccf1aa..63d7920 100644 --- a/testsuite/tests/nfs-options.out +++ b/testsuite/tests/nfs-options.out @@ -9,3 +9,5 @@ Return Unknown option: unknownoption Return Unknown option: unknownassignment Return Empty value for option: rsize Return Unknown option: two +Dump Nfs::Options::get_nfs41 +Dump Nfs::Options::set_nfs41 diff --git a/testsuite/tests/nfs-options.ycp b/testsuite/tests/nfs-options.ycp index a5ad6b0..1300685 100644 --- a/testsuite/tests/nfs-options.ycp +++ b/testsuite/tests/nfs-options.ycp @@ -1,6 +1,7 @@ { include "testsuite.ycp"; import "Nfs::Options"; + import "Assert"; DUMP ("Nfs::Options::validate"); TEST (``(Nfs::Options::validate ("")), [], nil); @@ -13,4 +14,58 @@ TEST (``(Nfs::Options::validate ("nolock,unknownassignment=true")), [], nil); TEST (``(Nfs::Options::validate ("nolock,rsize=")), [], nil); TEST (``(Nfs::Options::validate ("nolock,two=equal=signs")), [], nil); + + DUMP ("Nfs::Options::get_nfs41"); + Assert::Equal(false, Nfs::Options::get_nfs41("")); + Assert::Equal(false, Nfs::Options::get_nfs41("defaults")); + Assert::Equal(false, Nfs::Options::get_nfs41("ro,sync")); + Assert::Equal(false, Nfs::Options::get_nfs41("minorversion=0")); + Assert::Equal(true, Nfs::Options::get_nfs41("minorversion=1")); + // "minorversion=2" does not exist yet, YAGNI + Assert::Equal(false, Nfs::Options::get_nfs41("subminorversion=1")); // substring must not match + // Assert::Equal(?, Nfs::Options::get_nfs41("minorversion=1,minorversion=0")); // don't care + Assert::Equal(false, Nfs::Options::get_nfs41("ro,minorversion=0,sync")); + Assert::Equal(true, Nfs::Options::get_nfs41("ro,minorversion=1,sync")); + + DUMP ("Nfs::Options::set_nfs41"); + Assert::Equal( "", + Nfs::Options::set_nfs41("", false)); + Assert::Equal( "minorversion=1", + Nfs::Options::set_nfs41("", true)); + + Assert::Equal( "defaults", + Nfs::Options::set_nfs41("defaults", false)); + Assert::Equal( "minorversion=1", + Nfs::Options::set_nfs41("defaults", true)); + + Assert::Equal( "ro,sync", + Nfs::Options::set_nfs41("ro,sync", false)); + Assert::Equal( "ro,sync,minorversion=1", + Nfs::Options::set_nfs41("ro,sync", true)); + + Assert::Equal( "minorversion=0", + Nfs::Options::set_nfs41("minorversion=0", false)); + Assert::Equal( "minorversion=1", + Nfs::Options::set_nfs41("minorversion=0", true)); + + Assert::Equal( "defaults", + Nfs::Options::set_nfs41("minorversion=1", false)); + Assert::Equal( "minorversion=1", + Nfs::Options::set_nfs41("minorversion=1", true)); + + Assert::Equal( "subminorversion=1", + Nfs::Options::set_nfs41("subminorversion=1", false)); + Assert::Equal( "subminorversion=1,minorversion=1", + Nfs::Options::set_nfs41("subminorversion=1", true)); + + Assert::Equal( "ro,minorversion=0,sync", + Nfs::Options::set_nfs41("ro,minorversion=0,sync", false)); + Assert::Equal( "ro,sync,minorversion=1", + Nfs::Options::set_nfs41("ro,minorversion=0,sync", true)); + + Assert::Equal( "ro,sync", + Nfs::Options::set_nfs41("ro,minorversion=1,sync", false)); + Assert::Equal( "ro,minorversion=1,sync", + Nfs::Options::set_nfs41("ro,minorversion=1,sync", true)); + } From e0477793a1c673bf2782916b9491b8a0e3442f50 Mon Sep 17 00:00:00 2001 From: Martin Vidner Date: Fri, 14 Dec 2012 10:45:18 +0100 Subject: [PATCH 30/50] VERSION + .changes --- VERSION | 2 +- package/yast2-nfs-client.changes | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 8e9d016..be82b7c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.17.15 +2.17.16 diff --git a/package/yast2-nfs-client.changes b/package/yast2-nfs-client.changes index 00808c2..e9ec78d 100644 --- a/package/yast2-nfs-client.changes +++ b/package/yast2-nfs-client.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Fri Dec 14 10:41:23 CET 2012 - mvidner@suse.cz + +- Added minorvers=1 for pNFS, NFS4.1 (FATE#312259). +- 2.17.16 + ------------------------------------------------------------------- Fri Dec 14 10:35:14 CET 2012 - mvidner@suse.cz From 140023472725d4494a19f8d62b24e89f0a4ad4f2 Mon Sep 17 00:00:00 2001 From: Martin Vidner Date: Thu, 3 Jan 2013 11:33:33 +0100 Subject: [PATCH 31/50] Document which code in other projects determines the options including links to git repos. clickable FTW! --- src/modules/Nfs/Options.ycp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/modules/Nfs/Options.ycp b/src/modules/Nfs/Options.ycp index d8dccb6..acf9a48 100644 --- a/src/modules/Nfs/Options.ycp +++ b/src/modules/Nfs/Options.ycp @@ -17,7 +17,18 @@ global define string validate (string options) { list option_list = splitstring (options, ","); - //the options must be easy to sync with mount.c and nfsmount.c + // The options should be kept synced with the code that handles them, + // which is not an easy task, as there are many places: + // - util-linux.rpm + // man 8 mount + // https://git.kernel.org/?p=utils/util-linux/util-linux.git;a=history;f=libmount/src/optmap.c + // - nfs-client.rpm (nfs-utils.src.rpm) + // man 5 nfs + // http://git.linux-nfs.org/?p=steved/nfs-utils.git;a=history;f=utils/mount/nfsmount.c + // - kernel: fs/nfs/super.c + // http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=history;f=fs/nfs/super.c + // Note that minorversion in particular is mentioned only in the kernel + // but not in nfs-utils. WTF. // these can be negated by "no" list non_value = ["bg", "fg", "soft", "hard", "intr", "posix", "cto", "ac", "acl", From f230a03d25f2f80f23e8b5ab3a7e5c997d6ab9f1 Mon Sep 17 00:00:00 2001 From: Martin Vidner Date: Thu, 3 Jan 2013 15:14:33 +0100 Subject: [PATCH 32/50] doc comments, better constant names --- src/modules/Nfs/Options.ycp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/modules/Nfs/Options.ycp b/src/modules/Nfs/Options.ycp index acf9a48..a0b6e5e 100644 --- a/src/modules/Nfs/Options.ycp +++ b/src/modules/Nfs/Options.ycp @@ -75,17 +75,22 @@ global define string validate (string options) { /** FIXME: factor out get_nfs4(vfstype, options) (depending on n::o)! + * @param options fstab option string * @return is version >= 4.1 enabled */ global boolean get_nfs41(string options) { list option_list = splitstring (options, ","); - return contains(option_list, "minorversion=1"); + const string ENABLED = "minorversion=1"; + return contains(option_list, ENABLED); } /** * Add or remove minorversion=1 according to nfs41. * FIXME vfstype=nfs4 is deprecated in favor of nfsvers=4 (aka vers=4) + * @param options fstab option string + * @param nfs41 is version >= 4.1 enabled + * @return new fstab option string */ global define string set_nfs41(string options, boolean nfs41) { // don't mutate the string unnecessarily @@ -93,16 +98,16 @@ global define string set_nfs41(string options, boolean nfs41) { return options; } - const string OPT = "minorversion=1"; - const string CLEAN = "minorversion=0"; + const string ENABLED = "minorversion=1"; + const string DISABLED = "minorversion=0"; if (options == "defaults") { options = ""; } list option_list = splitstring(options, ","); - option_list = filter(string opt, option_list, ``( opt != OPT )); - option_list = filter(string opt, option_list, ``( opt != CLEAN )); + option_list = filter(string opt, option_list, ``( opt != ENABLED )); + option_list = filter(string opt, option_list, ``( opt != DISABLED )); if (nfs41) { - option_list = add(option_list, OPT); + option_list = add(option_list, ENABLED); } options = mergestring(option_list, ","); From 96bd39b70d4612df991ace4ce1a25b2d4aded7bc Mon Sep 17 00:00:00 2001 From: Martin Vidner Date: Tue, 15 Jan 2013 16:17:08 +0100 Subject: [PATCH 33/50] Nfs::Options::validate: readability thru better names ...and "const", foreach thx jreidinger! --- src/modules/Nfs/Options.ycp | 60 +++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 26 deletions(-) diff --git a/src/modules/Nfs/Options.ycp b/src/modules/Nfs/Options.ycp index a0b6e5e..f78bada 100644 --- a/src/modules/Nfs/Options.ycp +++ b/src/modules/Nfs/Options.ycp @@ -12,8 +12,6 @@ textdomain "nfs"; global define string validate (string options) { // To translators: error popup if (size (options) == 0) return _("Empty option strings are not allowed."); - if (options == "defaults") return ""; - list option_list = splitstring (options, ","); @@ -31,46 +29,56 @@ global define string validate (string options) { // but not in nfs-utils. WTF. // these can be negated by "no" - list non_value = ["bg", "fg", "soft", "hard", "intr", "posix", "cto", "ac", "acl", + const list NEGATABLE_OPTIONS = [ "bg", "fg", "soft", "hard", + "intr", "posix", "cto", "ac", "acl", "lock", "tcp", "udp", "rdirplus", // these are common for all fs types "atime", "auto", "dev", "exec", "group", "owner", "suid", "user", "users"]; + const list NEGATED_OPTIONS = maplist (string e, NEGATABLE_OPTIONS, ``(sformat ("no%1", e))); + // these cannot be negated // they are not nfs specific BTW - list non_value1 = ["defaults", "async", "sync", "dirsync", "ro", "rw", + const list SIMPLE_OPTIONS = ["defaults", + "async", "sync", "dirsync", "ro", "rw", "remount", "bind", "rbind", "_netdev", ]; - list with_value = ["rsize", "wsize", "timeo", "retrans", "acregmin", "acregmax", + const list OPTIONS_WITH_VALUE = ["rsize", "wsize", + "timeo", "retrans", "acregmin", "acregmax", "acdirmin", "acdirmin", "acdirmax", "actimeo", "retry", "namlen", "port", "proto", "clientaddr", "mountport", "mounthost", "mountprog", "mountvers", "nfsprog", "nfsvers", "vers", "minorversion", "sec" ]; - integer i = 0; - string current_option = ""; // first fiter out non value options and its nooptions forms (see nfs(5)) - option_list = filter (string e, option_list, ``(!contains (non_value, e))); - non_value = maplist (string e, non_value, ``(sformat ("no%1", e))); - option_list = filter (string e, option_list, ``(!contains (non_value, e))); - option_list = filter (string e, option_list, ``(!contains (non_value1, e))); + option_list = filter (string e, option_list, ``(!contains (NEGATABLE_OPTIONS, e))); + option_list = filter (string e, option_list, ``(!contains (NEGATED_OPTIONS, e))); + option_list = filter (string e, option_list, ``(!contains (SIMPLE_OPTIONS, e))); - while (i < size (option_list)) + string error_message = ""; + foreach (string opt, option_list, { - string opt = option_list[i]:""; - list value = splitstring (opt, "="); - string v0 = value[0]:""; - string v1 = value[1]:""; + list opt_tuple = splitstring (opt, "="); + string key = opt_tuple[0]:""; + string value = opt_tuple[1]:""; + // By now we have filtered out known options without values; + // so what is left is either unknown options, ... // FIXME: this also triggers for "intr=bogus" - // To translators: error popup - if (!contains (with_value, v0)) return sformat (_("Unknown option: %1"), v0); - // To translators: error popup - if (size (value) != 2) return sformat (_("Invalid option: %1"), opt); - // To translators: error popup - if (v1 == "") return sformat (_("Empty value for option: %1"), v0); - i = i + 1; - } - - return ""; + // because we should have considered '=' before the simple options + if (!contains (OPTIONS_WITH_VALUE, key)) + // To translators: error popup + error_message = sformat (_("Unknown option: %1"), key); + // ... or known ones with badly specified values + else if (size (opt_tuple) != 2) + // To translators: error popup + error_message = sformat (_("Invalid option: %1"), opt); + else if (value == "") + // To translators: error popup + error_message = sformat (_("Empty value for option: %1"), key); + if (error_message != "") + break; + }); + + return error_message; } /** From a67ee9b4be613a40b66a3a54aa4263d4f2bbaa71 Mon Sep 17 00:00:00 2001 From: Martin Vidner Date: Tue, 15 Jan 2013 16:28:12 +0100 Subject: [PATCH 34/50] Nfs::Options::validate: quote in error messages; more tests test "Invalid" case test simple=bogusvalue --- src/modules/Nfs/Options.ycp | 7 ++++--- testsuite/tests/nfs-options.out | 12 +++++++----- testsuite/tests/nfs-options.ycp | 2 ++ 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/modules/Nfs/Options.ycp b/src/modules/Nfs/Options.ycp index f78bada..3fb772d 100644 --- a/src/modules/Nfs/Options.ycp +++ b/src/modules/Nfs/Options.ycp @@ -64,16 +64,17 @@ global define string validate (string options) { // so what is left is either unknown options, ... // FIXME: this also triggers for "intr=bogus" // because we should have considered '=' before the simple options + // FIXME "'" + foo + "'" used not to break translations; merge it. if (!contains (OPTIONS_WITH_VALUE, key)) // To translators: error popup - error_message = sformat (_("Unknown option: %1"), key); + error_message = sformat (_("Unknown option: %1"), "'" + key + "'"); // ... or known ones with badly specified values else if (size (opt_tuple) != 2) // To translators: error popup - error_message = sformat (_("Invalid option: %1"), opt); + error_message = sformat (_("Invalid option: %1"), "'" + opt + "'"); else if (value == "") // To translators: error popup - error_message = sformat (_("Empty value for option: %1"), key); + error_message = sformat (_("Empty value for option: %1"), "'" + key + "'"); if (error_message != "") break; }); diff --git a/testsuite/tests/nfs-options.out b/testsuite/tests/nfs-options.out index 63d7920..8e7172a 100644 --- a/testsuite/tests/nfs-options.out +++ b/testsuite/tests/nfs-options.out @@ -4,10 +4,12 @@ Return Return Return Return -Return Unknown option: bg -Return Unknown option: unknownoption -Return Unknown option: unknownassignment -Return Empty value for option: rsize -Return Unknown option: two +Return Unknown option: ' bg' +Return Unknown option: 'unknownoption' +Return Unknown option: 'unknownassignment' +Return Empty value for option: 'rsize' +Return Unknown option: 'two' +Return Invalid option: 'retrans=trans=trans' +Return Unknown option: 'intr' Dump Nfs::Options::get_nfs41 Dump Nfs::Options::set_nfs41 diff --git a/testsuite/tests/nfs-options.ycp b/testsuite/tests/nfs-options.ycp index 1300685..35742d6 100644 --- a/testsuite/tests/nfs-options.ycp +++ b/testsuite/tests/nfs-options.ycp @@ -14,6 +14,8 @@ TEST (``(Nfs::Options::validate ("nolock,unknownassignment=true")), [], nil); TEST (``(Nfs::Options::validate ("nolock,rsize=")), [], nil); TEST (``(Nfs::Options::validate ("nolock,two=equal=signs")), [], nil); + TEST (``(Nfs::Options::validate ("nolock,retrans=trans=trans")), [], nil); + TEST (``(Nfs::Options::validate ("nolock,intr=bogus")), [], nil); DUMP ("Nfs::Options::get_nfs41"); Assert::Equal(false, Nfs::Options::get_nfs41("")); From 1084a2be684c13cf4bccb36f4b83c80b721d7042 Mon Sep 17 00:00:00 2001 From: Martin Vidner Date: Tue, 15 Jan 2013 16:37:27 +0100 Subject: [PATCH 35/50] Nfs::Options: factor out from_string, to_string --- src/modules/Nfs/Options.ycp | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/src/modules/Nfs/Options.ycp b/src/modules/Nfs/Options.ycp index 3fb772d..11ddc3c 100644 --- a/src/modules/Nfs/Options.ycp +++ b/src/modules/Nfs/Options.ycp @@ -3,6 +3,28 @@ module "Nfs::Options"; textdomain "nfs"; +/** + * Parse to an internal representation: + * Simply split by commas, but "defaults" is represented by the empty list + * @param options a fstab option string + * @return list of individual options + */ +list from_string(string options) { + if (options == "defaults") { options = ""; } + return splitstring (options, ","); +} + +/** + * Convert list of individual options to a fstab option string + * @param option_list list of individual options + * @return a fstab option string + */ +string to_string(list option_list) { + string options = mergestring(option_list, ","); + if (options == "") { options = "defaults"; } + return options; +} + /** * Checks the nfs options for /etc/fstab: * nonempty, comma separated list of foo,nofoo,bar=baz (see nfs(5)) @@ -13,7 +35,7 @@ global define string validate (string options) { // To translators: error popup if (size (options) == 0) return _("Empty option strings are not allowed."); - list option_list = splitstring (options, ","); + list option_list = from_string(options); // The options should be kept synced with the code that handles them, // which is not an easy task, as there are many places: @@ -88,7 +110,7 @@ FIXME: factor out get_nfs4(vfstype, options) (depending on n::o)! * @return is version >= 4.1 enabled */ global boolean get_nfs41(string options) { - list option_list = splitstring (options, ","); + list option_list = from_string(options); const string ENABLED = "minorversion=1"; return contains(option_list, ENABLED); @@ -110,8 +132,7 @@ global define string set_nfs41(string options, boolean nfs41) { const string ENABLED = "minorversion=1"; const string DISABLED = "minorversion=0"; - if (options == "defaults") { options = ""; } - list option_list = splitstring(options, ","); + list option_list = from_string(options); option_list = filter(string opt, option_list, ``( opt != ENABLED )); option_list = filter(string opt, option_list, ``( opt != DISABLED )); @@ -119,10 +140,7 @@ global define string set_nfs41(string options, boolean nfs41) { option_list = add(option_list, ENABLED); } - options = mergestring(option_list, ","); - if (options == "") { options = "defaults"; } - - return options; + return to_string(option_list); } /*EOF*/ From 24965d815ba59334192166736815ad9b296f14cf Mon Sep 17 00:00:00 2001 From: Martin Vidner Date: Tue, 15 Jan 2013 16:45:22 +0100 Subject: [PATCH 36/50] changelog: fixed misspelling; timestamp updated still OK to change the changelog before merging --- package/yast2-nfs-client.changes | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package/yast2-nfs-client.changes b/package/yast2-nfs-client.changes index e9ec78d..972cd1b 100644 --- a/package/yast2-nfs-client.changes +++ b/package/yast2-nfs-client.changes @@ -1,7 +1,7 @@ ------------------------------------------------------------------- -Fri Dec 14 10:41:23 CET 2012 - mvidner@suse.cz +Tue Jan 15 16:44:36 CET 2013 - mvidner@suse.cz -- Added minorvers=1 for pNFS, NFS4.1 (FATE#312259). +- Added minorversion=1 for pNFS, NFS4.1 (FATE#312259). - 2.17.16 ------------------------------------------------------------------- From c6fd2422f072b612132f884e05e5766719d5ba66 Mon Sep 17 00:00:00 2001 From: Martin Vidner Date: Fri, 18 Jan 2013 11:00:03 +0100 Subject: [PATCH 37/50] AutoYaST: tests for SP2 schema. --- testsuite/tests/autoyast.err | 0 testsuite/tests/autoyast.out | 9 +++++++++ testsuite/tests/autoyast.ycp | 39 ++++++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+) create mode 100644 testsuite/tests/autoyast.err create mode 100644 testsuite/tests/autoyast.out create mode 100644 testsuite/tests/autoyast.ycp diff --git a/testsuite/tests/autoyast.err b/testsuite/tests/autoyast.err new file mode 100644 index 0000000..e69de29 diff --git a/testsuite/tests/autoyast.out b/testsuite/tests/autoyast.out new file mode 100644 index 0000000..550f0b6 --- /dev/null +++ b/testsuite/tests/autoyast.out @@ -0,0 +1,9 @@ +Read .target.tmpdir nil +Log Failed to set temporary directory: nil +Dump Nfs::Import +Dump - basic, SLE11-SP2 +Dump -- and Export +Dump - empty +Dump - invalid, missing basic data +Log Missing at Import: 'mount_point'. +Log Missing at Import: 'nfs_options'. diff --git a/testsuite/tests/autoyast.ycp b/testsuite/tests/autoyast.ycp new file mode 100644 index 0000000..596e49f --- /dev/null +++ b/testsuite/tests/autoyast.ycp @@ -0,0 +1,39 @@ +{ + include "testsuite.ycp"; + import "Nfs"; + import "Assert"; + + DUMP("Nfs::Import"); + // --------- + DUMP("- basic, SLE11-SP2"); + map entry1 = $[ + "server_path": "data.example.com:/mirror", + "mount_point": "/mirror", + "nfs_options": "defaults" + ]; + + Nfs::Import([ entry1 ]); + Assert::Equal(1, size(Nfs::nfs_entries)); + Assert::Equal("data.example.com:/mirror", Nfs::nfs_entries[0, "spec"]:""); + + DUMP("-- and Export"); + list e = Nfs::Export(); + Assert::Equal(1, size(e)); + Assert::Equal("data.example.com:/mirror", e[1, "server_path"]:""); + Assert::Equal("/mirror", e[1, "mount_point"]:""); + Assert::Equal("defaults", e[1, "nfs_options"]:""); + + // --------- + DUMP("- empty"); + Nfs::Import([]); + Assert::Equal(0, size(Nfs::nfs_entries)); + + // --------- + DUMP("- invalid, missing basic data"); + map entry_invalid = $[ + "server_path": "data.example.com:/mirror", + ]; + + Nfs::Import([ entry_invalid ]); + Assert::Equal(0, size(Nfs::nfs_entries)); +} From 8ccdfc05464fe39e6344e2498cbbe21c5369692e Mon Sep 17 00:00:00 2001 From: Martin Vidner Date: Fri, 18 Jan 2013 14:56:33 +0100 Subject: [PATCH 38/50] AutoYaST: fix to allow NFS4 options (FATE#312242, bnc#457981) Backported from 29e91e5e406e7ef9647810b92b462c478d46a9c9 BUT! changed the schema to keep compatibility with SLE11-SP2. Nfs.ycp: removing a public function Nfs::Set which is not used anywhere else. Namely not in - autoyast2 - yast2-backup - yast2-installation - yast2-nfs-client - yast2-nfs-server --- src/modules/Nfs.ycp | 96 +++++++++++++++++++++--------------- src/nfs.rnc | 24 +++++++-- testsuite/tests/autoyast.out | 11 ++++- testsuite/tests/autoyast.ycp | 56 +++++++++++++++++++-- 4 files changed, 139 insertions(+), 48 deletions(-) diff --git a/src/modules/Nfs.ycp b/src/modules/Nfs.ycp index e540433..28fe00b 100644 --- a/src/modules/Nfs.ycp +++ b/src/modules/Nfs.ycp @@ -83,21 +83,26 @@ // list of created directories list created_dirs = []; - /** - * Set module data - * @param settings module settings - * @return void - */ - global define void Set(list settings) ``{ - nfs_entries = maplist(map entry, settings, ``{ - return($[ - "spec":entry["server_path"]:"", - "file":entry["mount_point"]:"", - "vfstype":entry["vfstype"]:"", - "mntops":entry["nfs_options"]:"" - ]); - }); - return; + boolean ReadNfs4() { + return SCR::Read(.sysconfig.nfs.NFS4_SUPPORT) == "yes"; + } + + string ReadIdmapd() { + return (string) SCR::Read(.etc.idmapd_conf, "Domain"); + } + + + define boolean validate_ay_nfs_entry(map entry) { + boolean missing = false; + foreach (string k, ["server_path", "mount_point", "nfs_options"], + { + if (! haskey (entry, k)) + { + y2error ("Missing at Import: '%1'.", k); + missing = true; + } + }); + return !missing; } /** @@ -108,40 +113,48 @@ * @return success */ global define boolean Import (list settings) ``{ + map global_options = $[]; + // first the compat switch + if (haskey (settings[0]:$[], "enable_nfs4")) { + global_options = settings[0]:$[]; + settings = remove(settings, 0); + } + + list > entries = (list >) settings; + // ... - boolean missing = false; - settings = maplist(map s,settings,``{ - foreach (string k, ["server_path", "mount_point", "nfs_options"], ``{ - if (! haskey (s, k)) - { - y2error ("Missing at Import: '%1'.", k); - missing = true; - } - }); + if (find(map e, entries, ``(! validate_ay_nfs_entry(e)) ) != nil) { + return false; + } + entries = maplist(map e, entries, { //Backwards compatibility: with FaTE#302031, we support nfsv4 mounts //thus we need to keep info on nfs version (v3 vs. v4) //But older AY profiles might not contain this element //so let's assume nfsv3 in that case (#395850) - if ( !haskey(s, "vfstype") ) + if ( !haskey(e, "vfstype") ) { - s["vfstype"] = "nfs"; - } else { - if (s["vfstype"]:"nfs" == "nfs4") - { - nfs4_enabled = true; - } + e["vfstype"] = "nfs"; } - return s; - + return e; }); - if (missing) - { - return false; - } + nfs4_enabled = global_options["enable_nfs4"]:ReadNfs4(); + idmapd_domain = global_options["idmapd_domain"]:ReadIdmapd(); + + nfs_entries = maplist(map entry, entries, { + // vfstype can override a missing enable_nfs4 + if (entry["vfstype"]:"" == "nfs4") { + nfs4_enabled = true; + } + return($[ + "spec":entry["server_path"]:"", + "file":entry["mount_point"]:"", + "vfstype":entry["vfstype"]:"", + "mntops":entry["nfs_options"]:"" + ]); + }); - Set(settings); return true; } @@ -158,7 +171,12 @@ "nfs_options":entry["mntops"]:"" ]); }); - return entries; + map options = $[ + "enable_nfs4": nfs4_enabled, + "idmapd_domain": idmapd_domain + ]; + // FIXME: now the list is always nonempty; is that OK? + return prepend(entries, options); } /* ------------------------------------------------------------ */ diff --git a/src/nfs.rnc b/src/nfs.rnc index 20ce1f7..3491a2a 100644 --- a/src/nfs.rnc +++ b/src/nfs.rnc @@ -1,10 +1,26 @@ -nfs = - element nfs { - LIST, - element nfs_entry { +# hack: the list is heterogeneous, +# with an optional first entry which carries the global options +# bnc#... + +nfs_global_options_content = ( + element enable_nfs4 { BOOLEAN }? & + element idmapd_domain { text }? +) + +nfs_entry_content = ( element server_path { text } & element mount_point { text } & element vfstype {text}? & element nfs_options { text } +) + +nfs = + element nfs { + LIST, + element nfs_entry { + nfs_global_options_content + }? , + element nfs_entry { + nfs_entry_content }* } diff --git a/testsuite/tests/autoyast.out b/testsuite/tests/autoyast.out index 550f0b6..c2409c8 100644 --- a/testsuite/tests/autoyast.out +++ b/testsuite/tests/autoyast.out @@ -1,9 +1,16 @@ -Read .target.tmpdir nil -Log Failed to set temporary directory: nil +Read .target.tmpdir "/tmp" Dump Nfs::Import Dump - basic, SLE11-SP2 +Read .sysconfig.nfs.NFS4_SUPPORT "no" +Read .etc.idmapd_conf "Domain" "localdomain" +Return true Dump -- and Export Dump - empty +Read .sysconfig.nfs.NFS4_SUPPORT "no" +Read .etc.idmapd_conf "Domain" "localdomain" +Return true Dump - invalid, missing basic data Log Missing at Import: 'mount_point'. Log Missing at Import: 'nfs_options'. +Dump - basic, SLE11-SP3 +Dump -- and Export diff --git a/testsuite/tests/autoyast.ycp b/testsuite/tests/autoyast.ycp index 596e49f..b6010ce 100644 --- a/testsuite/tests/autoyast.ycp +++ b/testsuite/tests/autoyast.ycp @@ -1,5 +1,25 @@ { include "testsuite.ycp"; + map I_READ = $[ + "target" : $[ + "tmpdir" : "/tmp", + ], + ]; + map I_WRITE = $[]; + map I_EXEC = $[]; + TESTSUITE_INIT ([I_READ, I_WRITE, I_EXEC], nil); + + map READ = $[ + "etc": $[ + "idmapd_conf" : "localdomain", + ], + "sysconfig": $[ + "nfs" : $[ + "NFS4_SUPPORT": "no", + ], + ], + ]; + import "Nfs"; import "Assert"; @@ -12,20 +32,26 @@ "nfs_options": "defaults" ]; - Nfs::Import([ entry1 ]); + TEST (``( + Nfs::Import([ entry1 ]) + ), [READ, $[], $[]], nil); Assert::Equal(1, size(Nfs::nfs_entries)); Assert::Equal("data.example.com:/mirror", Nfs::nfs_entries[0, "spec"]:""); DUMP("-- and Export"); list e = Nfs::Export(); - Assert::Equal(1, size(e)); + Assert::Equal(2, size(e)); + Assert::Equal(true, haskey(e[0]:$[], "enable_nfs4")); + Assert::Equal(true, haskey(e[0]:$[], "idmapd_domain")); Assert::Equal("data.example.com:/mirror", e[1, "server_path"]:""); Assert::Equal("/mirror", e[1, "mount_point"]:""); Assert::Equal("defaults", e[1, "nfs_options"]:""); // --------- DUMP("- empty"); - Nfs::Import([]); + TEST (``( + Nfs::Import([]) + ), [READ, $[], $[]], nil); Assert::Equal(0, size(Nfs::nfs_entries)); // --------- @@ -36,4 +62,28 @@ Nfs::Import([ entry_invalid ]); Assert::Equal(0, size(Nfs::nfs_entries)); + + // --------- + DUMP("- basic, SLE11-SP3"); + map global_options = $[ + "enable_nfs4": true, + "idmapd_domain": "example.com" + ]; + Nfs::Import([ + global_options, + entry1 + ]); + Assert::Equal(true, Nfs::nfs4_enabled); + Assert::Equal("example.com", Nfs::idmapd_domain); + Assert::Equal(1, size(Nfs::nfs_entries)); + Assert::Equal("data.example.com:/mirror", Nfs::nfs_entries[0, "spec"]:""); + + DUMP("-- and Export"); + e = Nfs::Export(); + Assert::Equal(2, size(e)); + Assert::Equal(true, e[0, "enable_nfs4"]:false); + Assert::Equal("example.com", e[0, "idmapd_domain"]:""); + Assert::Equal("data.example.com:/mirror", e[1, "server_path"]:""); + Assert::Equal("/mirror", e[1, "mount_point"]:""); + Assert::Equal("defaults", e[1, "nfs_options"]:""); } From 54da3fdb3589d6ab9bef1500299f363939b74c83 Mon Sep 17 00:00:00 2001 From: Martin Vidner Date: Fri, 18 Jan 2013 14:07:23 +0100 Subject: [PATCH 39/50] .changes --- package/yast2-nfs-client.changes | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/package/yast2-nfs-client.changes b/package/yast2-nfs-client.changes index 972cd1b..743606e 100644 --- a/package/yast2-nfs-client.changes +++ b/package/yast2-nfs-client.changes @@ -1,3 +1,8 @@ +------------------------------------------------------------------- +Fri Jan 18 14:05:54 CET 2013 - mvidner@suse.cz + +- AutoYaST: fix to allow NFS4 options (FATE#312242, bnc#457981) + ------------------------------------------------------------------- Tue Jan 15 16:44:36 CET 2013 - mvidner@suse.cz From 9a5075e0bffb6854f5e424ef66441555c4e597e9 Mon Sep 17 00:00:00 2001 From: Martin Vidner Date: Fri, 18 Jan 2013 14:19:33 +0100 Subject: [PATCH 40/50] Added option for enabling NFS4 GSS (FATE#312242, bnc#681190) backported from 29f5fb6c167ca097784624cb1e581cc569e1ef9c --- VERSION | 2 +- package/yast2-nfs-client.changes | 2 ++ src/include/nfs/ui.ycp | 36 ++++++++++++++++++-------------- src/modules/Nfs.ycp | 16 +++++++++++--- src/nfs.rnc | 1 + testsuite/tests/autoyast.out | 7 +++++++ testsuite/tests/autoyast.ycp | 31 +++++++++++++++++++++++++-- testsuite/tests/readwrite.out | 2 ++ testsuite/tests/readwrite.ycp | 1 + testsuite/tests/readwrite2.out | 8 +++++++ testsuite/tests/readwrite2.ycp | 1 + 11 files changed, 85 insertions(+), 22 deletions(-) diff --git a/VERSION b/VERSION index be82b7c..e2797f9 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.17.16 +2.17.17 diff --git a/package/yast2-nfs-client.changes b/package/yast2-nfs-client.changes index 743606e..6e4b3f5 100644 --- a/package/yast2-nfs-client.changes +++ b/package/yast2-nfs-client.changes @@ -2,6 +2,8 @@ Fri Jan 18 14:05:54 CET 2013 - mvidner@suse.cz - AutoYaST: fix to allow NFS4 options (FATE#312242, bnc#457981) +- added option for enabling NFS4 GSS (FATE#312242, bnc#681190) +- 2.17.17 ------------------------------------------------------------------- Tue Jan 15 16:44:36 CET 2013 - mvidner@suse.cz diff --git a/src/include/nfs/ui.ycp b/src/include/nfs/ui.ycp index dd21230..c2f4b80 100644 --- a/src/include/nfs/ui.ycp +++ b/src/include/nfs/ui.ycp @@ -242,28 +242,28 @@ `VBox( `VSpacing(0.2), `HBox( - TextAndButton ( - `ComboBox( - `id(`serverent),`opt(`editable), - // text entry label - _("&NFS Server Hostname"), servers ), - // pushbutton label - // choose a host from a list - // appears in help text too - `PushButton (`id (`choose), _("Choo&se")) - ), + TextAndButton ( + `ComboBox( + `id(`serverent),`opt(`editable), + // text entry label + _("&NFS Server Hostname"), servers ), + // pushbutton label + // choose a host from a list + // appears in help text too + `PushButton (`id (`choose), _("Choo&se")) + ), `HSpacing(0.5), - TextAndButton ( + TextAndButton ( `InputField( `id(`pathent), - `opt(`hstretch), - // textentry label - _("&Remote Directory"), pth), - // pushbutton label, + `opt(`hstretch), + // textentry label + _("&Remote Directory"), pth), + // pushbutton label, // select from a list of remote filesystems // make it short // appears in help text too `PushButton (`id (`pathent_list), _("&Select")) - ) + ) ), `Left( `HBox( @@ -532,6 +532,8 @@ rights.

") + fw_cwm_widget["help"]:""; `HStretch() ), `VSpacing (1), + `Left(`CheckBox(`id(`enable_nfs_gss), `opt( `notify), _("Enable &GSS Security"))), + `VSpacing (1), fw_cwm_widget["custom_widget"]:`Empty (), `VStretch() ); @@ -566,6 +568,7 @@ rights.

") + fw_cwm_widget["help"]:""; UI::ChangeWidget(`id(`enable_nfs4), `Value, Nfs::nfs4_enabled != false); UI::ChangeWidget( `id(`nfs4_domain), `Enabled, Nfs::nfs4_enabled != false); UI::ChangeWidget(`id(`nfs4_domain), `Value, Nfs::idmapd_domain); + UI::ChangeWidget(`id(`enable_nfs_gss), `Value, Nfs::nfs_gss_enabled != false); } void SaveFstabEntries( ) @@ -577,6 +580,7 @@ rights.

") + fw_cwm_widget["help"]:""; { CWMFirewallInterfaces::OpenFirewallStore (fw_cwm_widget, "", event); Nfs::nfs4_enabled = (boolean) UI::QueryWidget(`id(`enable_nfs4),`Value); + Nfs::nfs_gss_enabled = (boolean) UI::QueryWidget(`id(`enable_nfs_gss),`Value); Nfs::idmapd_domain = (string) UI::QueryWidget(`id(`nfs4_domain),`Value); } diff --git a/src/modules/Nfs.ycp b/src/modules/Nfs.ycp index 28fe00b..4e706b3 100644 --- a/src/modules/Nfs.ycp +++ b/src/modules/Nfs.ycp @@ -76,6 +76,8 @@ global boolean nfs4_enabled = nil; + global boolean nfs_gss_enabled = nil; + global string idmapd_domain = ""; string portmapper = ""; @@ -87,7 +89,11 @@ return SCR::Read(.sysconfig.nfs.NFS4_SUPPORT) == "yes"; } - string ReadIdmapd() { + boolean ReadNfsGss () { + return SCR::Read(.sysconfig.nfs.NFS_SECURITY_GSS) == "yes"; + } + + string ReadIdmapd() { return (string) SCR::Read(.etc.idmapd_conf, "Domain"); } @@ -140,6 +146,7 @@ }); nfs4_enabled = global_options["enable_nfs4"]:ReadNfs4(); + nfs_gss_enabled = global_options["enable_nfs_gss"]:ReadNfsGss(); idmapd_domain = global_options["idmapd_domain"]:ReadIdmapd(); nfs_entries = maplist(map entry, entries, { @@ -173,6 +180,7 @@ }); map options = $[ "enable_nfs4": nfs4_enabled, + "enable_nfs_gss": nfs_gss_enabled, "idmapd_domain": idmapd_domain ]; // FIXME: now the list is always nonempty; is that OK? @@ -292,8 +300,9 @@ }); } - nfs4_enabled = (SCR::Read(.sysconfig.nfs.NFS4_SUPPORT)=="yes"); - idmapd_domain = (string) SCR::Read(.etc.idmapd_conf, "Domain"); + nfs4_enabled = ReadNfs4(); + nfs_gss_enabled = ReadNfsGss(); + idmapd_domain = ReadIdmapd(); boolean progress_orig = Progress::set(false); SuSEFirewall::Read (); @@ -388,6 +397,7 @@ the NFS client configuration.\n")); { SCR::Write(.sysconfig.nfs.NFS4_SUPPORT,"no"); } + SCR::Write( .sysconfig.nfs.NFS_SECURITY_GSS, nfs_gss_enabled ? "yes" : "no"); boolean progress_orig = Progress::set (false); SuSEFirewall::WriteOnly (); Progress::set (progress_orig); diff --git a/src/nfs.rnc b/src/nfs.rnc index 3491a2a..8ca4964 100644 --- a/src/nfs.rnc +++ b/src/nfs.rnc @@ -4,6 +4,7 @@ nfs_global_options_content = ( element enable_nfs4 { BOOLEAN }? & + element enable_nfs_gss { BOOLEAN }? & element idmapd_domain { text }? ) diff --git a/testsuite/tests/autoyast.out b/testsuite/tests/autoyast.out index c2409c8..f518b59 100644 --- a/testsuite/tests/autoyast.out +++ b/testsuite/tests/autoyast.out @@ -2,15 +2,22 @@ Read .target.tmpdir "/tmp" Dump Nfs::Import Dump - basic, SLE11-SP2 Read .sysconfig.nfs.NFS4_SUPPORT "no" +Read .sysconfig.nfs.NFS_SECURITY_GSS "no" Read .etc.idmapd_conf "Domain" "localdomain" Return true Dump -- and Export Dump - empty Read .sysconfig.nfs.NFS4_SUPPORT "no" +Read .sysconfig.nfs.NFS_SECURITY_GSS "no" Read .etc.idmapd_conf "Domain" "localdomain" Return true Dump - invalid, missing basic data Log Missing at Import: 'mount_point'. Log Missing at Import: 'nfs_options'. Dump - basic, SLE11-SP3 +Read .sysconfig.nfs.NFS_SECURITY_GSS "no" +Return true +Dump -- and Export +Dump - with GSS +Return true Dump -- and Export diff --git a/testsuite/tests/autoyast.ycp b/testsuite/tests/autoyast.ycp index b6010ce..1e6623c 100644 --- a/testsuite/tests/autoyast.ycp +++ b/testsuite/tests/autoyast.ycp @@ -16,6 +16,7 @@ "sysconfig": $[ "nfs" : $[ "NFS4_SUPPORT": "no", + "NFS_SECURITY_GSS": "no", ], ], ]; @@ -69,10 +70,12 @@ "enable_nfs4": true, "idmapd_domain": "example.com" ]; - Nfs::Import([ + TEST (``( + Nfs::Import([ global_options, entry1 - ]); + ]) + ), [READ, $[], $[]], nil); Assert::Equal(true, Nfs::nfs4_enabled); Assert::Equal("example.com", Nfs::idmapd_domain); Assert::Equal(1, size(Nfs::nfs_entries)); @@ -86,4 +89,28 @@ Assert::Equal("data.example.com:/mirror", e[1, "server_path"]:""); Assert::Equal("/mirror", e[1, "mount_point"]:""); Assert::Equal("defaults", e[1, "nfs_options"]:""); + + // --------- + DUMP("- with GSS"); + global_options = $[ + "enable_nfs4": true, + "enable_nfs_gss": true, + "idmapd_domain": "example.com" + ]; + TEST (``( + Nfs::Import([ + global_options, + entry1 + ]) + ), [READ, $[], $[]], nil); + // assertions shortened + Assert::Equal(true, Nfs::nfs_gss_enabled); + Assert::Equal(1, size(Nfs::nfs_entries)); + Assert::Equal("data.example.com:/mirror", Nfs::nfs_entries[0, "spec"]:""); + + DUMP("-- and Export"); + e = Nfs::Export(); + Assert::Equal(2, size(e)); + Assert::Equal(true, e[0, "enable_nfs_gss"]:false); + Assert::Equal("data.example.com:/mirror", e[1, "server_path"]:""); } diff --git a/testsuite/tests/readwrite.out b/testsuite/tests/readwrite.out index 66bba4f..c1e89c9 100644 --- a/testsuite/tests/readwrite.out +++ b/testsuite/tests/readwrite.out @@ -1,6 +1,7 @@ Dump Read Read .etc.fstab [$["file":"/", "freq":1, "mntops":"defaults", "passno":2, "spec":"/dev/hda6", "vfstype":"reiserfs"], $["file":"/home", "freq":0, "mntops":"defaults", "passno":0, "spec":"foo.bar.com:/home", "vfstype":"nfs"], $["file":"/var/spool/mail", "freq":0, "mntops":"defaults", "passno":0, "spec":"foo.bar.com:/var/spool/mail", "vfstype":"nfs"], $["file":"/a\\040space", "freq":1, "mntops":"defaults", "passno":3, "spec":"/dev/hda7", "vfstype":"reiserfs"], $["file":"/b\\040space", "freq":0, "mntops":"defaults", "passno":0, "spec":"foo.bar.com:/space\\040dir", "vfstype":"nfs"]] Read .sysconfig.nfs.NFS4_SUPPORT "yes" +Read .sysconfig.nfs.NFS_SECURITY_GSS "yes" Read .etc.idmapd_conf "Domain" "localhost" Read .init.scripts.exists "SuSEfirewall2_init" true Read .init.scripts.runlevel "SuSEfirewall2_init" $["network":$["start":[], "stop":[]], "networkmanager":$["start":["3", "5"], "stop":["3", "5"]], "nfs":$["start":["3", "5"], "stop":["3", "5"]], "nfsboot":$["start":[], "stop":[]], "portmap":$["start":["3", "5"], "stop":["3", "5"]]] @@ -32,6 +33,7 @@ Read .init.scripts.comment "nfsboot" $["nfs":$[], "portmap":$[]] Execute .target.bash_output "/sbin/insserv -d /etc/init.d/nfsboot" $["exit":0, "stderr":"", "stdout":""] Write .sysconfig.nfs.NFS4_SUPPORT "yes" true Write .etc.idmapd_conf ["Domain", "localhost"] true +Write .sysconfig.nfs.NFS_SECURITY_GSS "yes" true Read .init.scripts.exists "nfs" true Execute .target.bash_output "/etc/init.d/nfs stop" $["TERM":"raw"] $["exit":0, "stderr":"", "stdout":""] Read .init.scripts.exists "portmap" true diff --git a/testsuite/tests/readwrite.ycp b/testsuite/tests/readwrite.ycp index a662fd6..ba29464 100644 --- a/testsuite/tests/readwrite.ycp +++ b/testsuite/tests/readwrite.ycp @@ -118,6 +118,7 @@ "sysconfig": $[ "nfs" : $[ "NFS4_SUPPORT": "yes", + "NFS_SECURITY_GSS": "yes", ], ], ]; diff --git a/testsuite/tests/readwrite2.out b/testsuite/tests/readwrite2.out index ddada98..44856af 100644 --- a/testsuite/tests/readwrite2.out +++ b/testsuite/tests/readwrite2.out @@ -3,6 +3,7 @@ Dump Read - nfs is in use & running Dump Read .etc.fstab [$["file":"/", "freq":1, "mntops":"defaults", "passno":2, "spec":"/dev/hda6", "vfstype":"reiserfs"], $["file":"/home", "freq":0, "mntops":"defaults", "passno":0, "spec":"foo.bar.com:/home", "vfstype":"nfs"], $["file":"/var/spool/mail", "freq":0, "mntops":"defaults", "passno":0, "spec":"foo.bar.com:/var/spool/mail", "vfstype":"nfs"], $["file":"/a\\040space", "freq":1, "mntops":"defaults", "passno":3, "spec":"/dev/hda7", "vfstype":"reiserfs"], $["file":"/b\\040space", "freq":0, "mntops":"defaults", "passno":0, "spec":"foo.bar.com:/space\\040dir", "vfstype":"nfs"]] Read .sysconfig.nfs.NFS4_SUPPORT "no" +Read .sysconfig.nfs.NFS_SECURITY_GSS "no" Read .etc.idmapd_conf "Domain" "localhost" Read .init.scripts.exists "SuSEfirewall2_init" true Read .init.scripts.runlevel "SuSEfirewall2_init" $["nfs":$["start":["3", "5"], "stop":["3", "5"]], "portmap":$["start":["3", "5"], "stop":["3", "5"]]] @@ -35,6 +36,7 @@ Read .init.scripts.runlevel "nfsboot" $["nfs":$["start":["3", "5"], "stop":["3", Read .init.scripts.comment "nfsboot" $["nfs":$[], "portmap":$[]] Execute .target.bash_output "/sbin/insserv -d /etc/init.d/nfsboot" $["exit":0, "stderr":"", "stdout":""] Write .sysconfig.nfs.NFS4_SUPPORT "no" true +Write .sysconfig.nfs.NFS_SECURITY_GSS "no" true Read .init.scripts.exists "nfs" true Execute .target.bash_output "/etc/init.d/nfs stop" $["TERM":"raw"] $["exit":0, "stderr":"", "stdout":""] Read .init.scripts.exists "portmap" true @@ -51,6 +53,7 @@ Dump Read - nfs is in use & stopped Dump Read .etc.fstab [$["file":"/", "freq":1, "mntops":"defaults", "passno":2, "spec":"/dev/hda6", "vfstype":"reiserfs"], $["file":"/home", "freq":0, "mntops":"defaults", "passno":0, "spec":"foo.bar.com:/home", "vfstype":"nfs"], $["file":"/var/spool/mail", "freq":0, "mntops":"defaults", "passno":0, "spec":"foo.bar.com:/var/spool/mail", "vfstype":"nfs"], $["file":"/a\\040space", "freq":1, "mntops":"defaults", "passno":3, "spec":"/dev/hda7", "vfstype":"reiserfs"], $["file":"/b\\040space", "freq":0, "mntops":"defaults", "passno":0, "spec":"foo.bar.com:/space\\040dir", "vfstype":"nfs"]] Read .sysconfig.nfs.NFS4_SUPPORT "no" +Read .sysconfig.nfs.NFS_SECURITY_GSS "no" Read .etc.idmapd_conf "Domain" "localhost" Return true Dump @@ -81,6 +84,7 @@ Read .init.scripts.runlevel "nfsboot" $["nfs":$["start":[], "stop":[]], "portmap Read .init.scripts.comment "nfsboot" $["nfs":$[], "portmap":$[]] Execute .target.bash_output "/sbin/insserv -d /etc/init.d/nfsboot" $["exit":0, "stderr":"", "stdout":""] Write .sysconfig.nfs.NFS4_SUPPORT "no" true +Write .sysconfig.nfs.NFS_SECURITY_GSS "no" true Read .init.scripts.exists "nfs" true Execute .target.bash_output "/etc/init.d/nfs stop" $["TERM":"raw"] $["exit":0, "stderr":"", "stdout":""] Read .init.scripts.exists "portmap" true @@ -97,6 +101,7 @@ Dump Read - nfs not used & running Dump Read .etc.fstab [$["file":"/", "freq":1, "mntops":"defaults", "passno":2, "spec":"/dev/hda6", "vfstype":"ext3"]] Read .sysconfig.nfs.NFS4_SUPPORT "no" +Read .sysconfig.nfs.NFS_SECURITY_GSS "no" Read .etc.idmapd_conf "Domain" "localhost" Return true Dump @@ -106,6 +111,7 @@ Read .etc.fstab [$["file":"/", "freq":1, "mntops":"defaults", "passno":2, "spec" Execute .target.bash "/bin/cp $ORIG $BACKUP" $["BACKUP":"/etc/fstab.YaST2.save", "ORIG":"/etc/fstab"] 0 Write .etc.fstab [$["file":"/", "freq":1, "mntops":"defaults", "passno":2, "spec":"/dev/hda6", "vfstype":"ext3"]] true Write .sysconfig.nfs.NFS4_SUPPORT "no" true +Write .sysconfig.nfs.NFS_SECURITY_GSS "no" true Read .init.scripts.exists "nfs" true Execute .target.bash_output "/etc/init.d/nfs stop" $["TERM":"raw"] $["exit":0, "stderr":"", "stdout":""] Read .init.scripts.exists "SuSEfirewall2_init" true @@ -116,6 +122,7 @@ Dump Read - nfs not used & services are stopped Dump Read .etc.fstab [$["file":"/", "freq":1, "mntops":"defaults", "passno":2, "spec":"/dev/hda6", "vfstype":"ext3"]] Read .sysconfig.nfs.NFS4_SUPPORT "no" +Read .sysconfig.nfs.NFS_SECURITY_GSS "no" Read .etc.idmapd_conf "Domain" "localhost" Return true Dump @@ -125,6 +132,7 @@ Read .etc.fstab [$["file":"/", "freq":1, "mntops":"defaults", "passno":2, "spec" Execute .target.bash "/bin/cp $ORIG $BACKUP" $["BACKUP":"/etc/fstab.YaST2.save", "ORIG":"/etc/fstab"] 0 Write .etc.fstab [$["file":"/", "freq":1, "mntops":"defaults", "passno":2, "spec":"/dev/hda6", "vfstype":"ext3"]] true Write .sysconfig.nfs.NFS4_SUPPORT "no" true +Write .sysconfig.nfs.NFS_SECURITY_GSS "no" true Read .init.scripts.exists "nfs" true Execute .target.bash_output "/etc/init.d/nfs stop" $["TERM":"raw"] $["exit":0, "stderr":"", "stdout":""] Read .init.scripts.exists "SuSEfirewall2_init" true diff --git a/testsuite/tests/readwrite2.ycp b/testsuite/tests/readwrite2.ycp index 3d27dd7..d3ab0f6 100644 --- a/testsuite/tests/readwrite2.ycp +++ b/testsuite/tests/readwrite2.ycp @@ -115,6 +115,7 @@ "sysconfig": $[ "nfs" : $[ "NFS4_SUPPORT": "no", + "NFS_SECURITY_GSS": "no", ], ], ]; From 5cea0910fe43c62e1e606b39796b27a599b779f8 Mon Sep 17 00:00:00 2001 From: Martin Vidner Date: Wed, 22 May 2013 13:54:01 +0200 Subject: [PATCH 41/50] refactoring according to code review - split out GetOptionsAndEntries, FillEntriesDefaults - no snake_case - add missing bnc reference - unify indentation --- src/modules/Nfs.ycp | 68 ++++++++++++++++++++++++++++----------------- src/nfs.rnc | 2 +- 2 files changed, 43 insertions(+), 27 deletions(-) diff --git a/src/modules/Nfs.ycp b/src/modules/Nfs.ycp index 4e706b3..05d9a5f 100644 --- a/src/modules/Nfs.ycp +++ b/src/modules/Nfs.ycp @@ -93,12 +93,12 @@ return SCR::Read(.sysconfig.nfs.NFS_SECURITY_GSS) == "yes"; } - string ReadIdmapd() { + string ReadIdmapd() { return (string) SCR::Read(.etc.idmapd_conf, "Domain"); } - define boolean validate_ay_nfs_entry(map entry) { + boolean ValidateAyNfsEntry(map entry) { boolean missing = false; foreach (string k, ["server_path", "mount_point", "nfs_options"], { @@ -111,29 +111,25 @@ return !missing; } + /** - * Get all NFS configuration from a map. - * When called by nfs_auto (preparing autoinstallation data) - * the map may be empty. - * @param settings a map with a single key: nfs_entries - * @return success + * From settings (which is a list in SLE11 but a map in oS: bnc#820989), + * extract the options and the NFS fstab entries. */ - global define boolean Import (list settings) ``{ - map global_options = $[]; - // first the compat switch + void GetOptionsAndEntries(list settings, map & global_options, list > & entries) { if (haskey (settings[0]:$[], "enable_nfs4")) { global_options = settings[0]:$[]; settings = remove(settings, 0); } - list > entries = (list >) settings; - // ... - - if (find(map e, entries, ``(! validate_ay_nfs_entry(e)) ) != nil) { - return false; - } + entries = (list >) settings; + } - entries = maplist(map e, entries, { + /** + * Fill in the defaults for AY profile entries. + */ + list > FillEntriesDefaults(list > entries) { + return maplist(map e, entries, { //Backwards compatibility: with FaTE#302031, we support nfsv4 mounts //thus we need to keep info on nfs version (v3 vs. v4) //But older AY profiles might not contain this element @@ -144,23 +140,43 @@ } return e; }); + } + + /** + * Get all NFS configuration from a map. + * When called by nfs_auto (preparing autoinstallation data) + * the map may be empty. + * @param settings a list of nfs_entries + * @return success + */ + global define boolean Import (list settings) ``{ + map global_options = $[]; + list > entries = []; + GetOptionsAndEntries(settings, global_options, entries); + + if (find(map e, entries, ``(! ValidateAyNfsEntry(e)) ) != nil) { + return false; + } + + entries = FillEntriesDefaults(entries); nfs4_enabled = global_options["enable_nfs4"]:ReadNfs4(); nfs_gss_enabled = global_options["enable_nfs_gss"]:ReadNfsGss(); idmapd_domain = global_options["idmapd_domain"]:ReadIdmapd(); - nfs_entries = maplist(map entry, entries, { - // vfstype can override a missing enable_nfs4 - if (entry["vfstype"]:"" == "nfs4") { + // vfstype can override a missing enable_nfs4 + if (find(map entry, entries, ``(entry["vfstype"]:"" == "nfs4")) != nil) { nfs4_enabled = true; - } - return($[ + } + + nfs_entries = maplist(map entry, entries, ``( + $[ "spec":entry["server_path"]:"", "file":entry["mount_point"]:"", "vfstype":entry["vfstype"]:"", "mntops":entry["nfs_options"]:"" - ]); - }); + ] + )); return true; } @@ -300,9 +316,9 @@ }); } - nfs4_enabled = ReadNfs4(); + nfs4_enabled = ReadNfs4(); nfs_gss_enabled = ReadNfsGss(); - idmapd_domain = ReadIdmapd(); + idmapd_domain = ReadIdmapd(); boolean progress_orig = Progress::set(false); SuSEFirewall::Read (); diff --git a/src/nfs.rnc b/src/nfs.rnc index 8ca4964..4d94804 100644 --- a/src/nfs.rnc +++ b/src/nfs.rnc @@ -1,6 +1,6 @@ # hack: the list is heterogeneous, # with an optional first entry which carries the global options -# bnc#... +# bnc#820989 nfs_global_options_content = ( element enable_nfs4 { BOOLEAN }? & From e74271d9ee9100657071c18b79646dc5347cda15 Mon Sep 17 00:00:00 2001 From: Martin Vidner Date: Wed, 22 May 2013 13:58:04 +0200 Subject: [PATCH 42/50] test the refactoring. caught a corner case --- src/modules/Nfs.ycp | 3 ++- testsuite/tests/autoyast.out | 5 +++++ testsuite/tests/autoyast.ycp | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/modules/Nfs.ycp b/src/modules/Nfs.ycp index 05d9a5f..6f60b3d 100644 --- a/src/modules/Nfs.ycp +++ b/src/modules/Nfs.ycp @@ -117,7 +117,8 @@ * extract the options and the NFS fstab entries. */ void GetOptionsAndEntries(list settings, map & global_options, list > & entries) { - if (haskey (settings[0]:$[], "enable_nfs4")) { + if (haskey (settings[0]:$[], "enable_nfs4") || + haskey (settings[0]:$[], "idmapd_domain")) { global_options = settings[0]:$[]; settings = remove(settings, 0); } diff --git a/testsuite/tests/autoyast.out b/testsuite/tests/autoyast.out index f518b59..2ebb9e1 100644 --- a/testsuite/tests/autoyast.out +++ b/testsuite/tests/autoyast.out @@ -18,6 +18,11 @@ Dump - basic, SLE11-SP3 Read .sysconfig.nfs.NFS_SECURITY_GSS "no" Return true Dump -- and Export +Dump - NFSv4 via vfstype +Read .sysconfig.nfs.NFS4_SUPPORT "no" +Read .sysconfig.nfs.NFS_SECURITY_GSS "no" +Return true +Dump -- and Export Dump - with GSS Return true Dump -- and Export diff --git a/testsuite/tests/autoyast.ycp b/testsuite/tests/autoyast.ycp index 1e6623c..5f6018e 100644 --- a/testsuite/tests/autoyast.ycp +++ b/testsuite/tests/autoyast.ycp @@ -90,6 +90,39 @@ Assert::Equal("/mirror", e[1, "mount_point"]:""); Assert::Equal("defaults", e[1, "nfs_options"]:""); + // --------- + DUMP("- NFSv4 via vfstype"); + map global_options2 = $[ + "idmapd_domain": "example.com" + ]; + map entry2 = $[ + "server_path": "data.example.com:/mirror", + "mount_point": "/mirror", + "nfs_options": "defaults", + "vfstype": "nfs4" + ]; + + TEST (``( + Nfs::Import([ + global_options2, + entry2 + ]) + ), [READ, $[], $[]], nil); + + Assert::Equal(true, Nfs::nfs4_enabled); + Assert::Equal("example.com", Nfs::idmapd_domain); + Assert::Equal(1, size(Nfs::nfs_entries)); + Assert::Equal("data.example.com:/mirror", Nfs::nfs_entries[0, "spec"]:""); + + DUMP("-- and Export"); + e = Nfs::Export(); + Assert::Equal(2, size(e)); + Assert::Equal(true, e[0, "enable_nfs4"]:false); + Assert::Equal("example.com", e[0, "idmapd_domain"]:""); + Assert::Equal("data.example.com:/mirror", e[1, "server_path"]:""); + Assert::Equal("/mirror", e[1, "mount_point"]:""); + Assert::Equal("defaults", e[1, "nfs_options"]:""); + // --------- DUMP("- with GSS"); global_options = $[ From ca5d7f87eb6710b0184e899c10632d3c5236cc31 Mon Sep 17 00:00:00 2001 From: Martin Vidner Date: Wed, 22 May 2013 14:23:05 +0200 Subject: [PATCH 43/50] .changes --- package/yast2-nfs-client.changes | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/package/yast2-nfs-client.changes b/package/yast2-nfs-client.changes index 6e4b3f5..84ab42c 100644 --- a/package/yast2-nfs-client.changes +++ b/package/yast2-nfs-client.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Wed May 22 12:21:21 UTC 2013 - mvidner@suse.cz + +- refactored the last change following a late review + (FATE#312242, bnc#820989) + ------------------------------------------------------------------- Fri Jan 18 14:05:54 CET 2013 - mvidner@suse.cz From 8d7557f48a22d16d123d4fc24607001c85b69a1a Mon Sep 17 00:00:00 2001 From: Martin Vidner Date: Tue, 30 Jul 2013 09:01:06 +0200 Subject: [PATCH 44/50] Fix Autoyast merge fallout found by tests. - test old Import as ImportAny (passing a list) - Export now produces a map --- src/modules/Nfs.ycp | 20 ++++++----- testsuite/tests/autoyast.out | 4 +-- testsuite/tests/autoyast.ycp | 66 +++++++++++++++++++----------------- 3 files changed, 49 insertions(+), 41 deletions(-) diff --git a/src/modules/Nfs.ycp b/src/modules/Nfs.ycp index b95e5d3..eaf7d5d 100644 --- a/src/modules/Nfs.ycp +++ b/src/modules/Nfs.ycp @@ -160,14 +160,7 @@ }); } - /** - * Get all NFS configuration from a map. - * When called by nfs_auto (preparing autoinstallation data) - * the map may be empty. - * @param settings a map($) of nfs_entries - * @return success - */ - global boolean Import (map settings) { + boolean ImportAny (any settings) { // ($) since oS-1x.x, settings was changed to be a map, // which is incompatible with the sle profiles; // it owuld be nice to make it compatible again @@ -203,6 +196,17 @@ return true; } + /** + * Get all NFS configuration from a map. + * When called by nfs_auto (preparing autoinstallation data) + * the map may be empty. + * @param settings a map($) of nfs_entries + * @return success + */ + global boolean Import (map settings) { + return ImportAny(settings); + } + /** * Dump the NFS settings to a map, for autoinstallation use. * @return a list of nfs entries. diff --git a/testsuite/tests/autoyast.out b/testsuite/tests/autoyast.out index 2ebb9e1..8e33e60 100644 --- a/testsuite/tests/autoyast.out +++ b/testsuite/tests/autoyast.out @@ -3,13 +3,13 @@ Dump Nfs::Import Dump - basic, SLE11-SP2 Read .sysconfig.nfs.NFS4_SUPPORT "no" Read .sysconfig.nfs.NFS_SECURITY_GSS "no" -Read .etc.idmapd_conf "Domain" "localdomain" +Read .etc.idmapd_conf.value.General.Domain "localdomain" Return true Dump -- and Export Dump - empty Read .sysconfig.nfs.NFS4_SUPPORT "no" Read .sysconfig.nfs.NFS_SECURITY_GSS "no" -Read .etc.idmapd_conf "Domain" "localdomain" +Read .etc.idmapd_conf.value.General.Domain "localdomain" Return true Dump - invalid, missing basic data Log Missing at Import: 'mount_point'. diff --git a/testsuite/tests/autoyast.ycp b/testsuite/tests/autoyast.ycp index 5f6018e..af0b093 100644 --- a/testsuite/tests/autoyast.ycp +++ b/testsuite/tests/autoyast.ycp @@ -34,24 +34,25 @@ ]; TEST (``( - Nfs::Import([ entry1 ]) + Nfs::ImportAny([ entry1 ]) ), [READ, $[], $[]], nil); Assert::Equal(1, size(Nfs::nfs_entries)); Assert::Equal("data.example.com:/mirror", Nfs::nfs_entries[0, "spec"]:""); DUMP("-- and Export"); - list e = Nfs::Export(); - Assert::Equal(2, size(e)); - Assert::Equal(true, haskey(e[0]:$[], "enable_nfs4")); - Assert::Equal(true, haskey(e[0]:$[], "idmapd_domain")); - Assert::Equal("data.example.com:/mirror", e[1, "server_path"]:""); - Assert::Equal("/mirror", e[1, "mount_point"]:""); - Assert::Equal("defaults", e[1, "nfs_options"]:""); + map ex = Nfs::Export(); + list e = ex["nfs_entries"]:[]; + Assert::Equal(1, size(e)); + Assert::Equal(true, haskey(ex, "enable_nfs4")); + Assert::Equal(true, haskey(ex, "idmapd_domain")); + Assert::Equal("data.example.com:/mirror", e[0, "server_path"]:""); + Assert::Equal("/mirror", e[0, "mount_point"]:""); + Assert::Equal("defaults", e[0, "nfs_options"]:""); // --------- DUMP("- empty"); TEST (``( - Nfs::Import([]) + Nfs::ImportAny([]) ), [READ, $[], $[]], nil); Assert::Equal(0, size(Nfs::nfs_entries)); @@ -61,7 +62,7 @@ "server_path": "data.example.com:/mirror", ]; - Nfs::Import([ entry_invalid ]); + Nfs::ImportAny([ entry_invalid ]); Assert::Equal(0, size(Nfs::nfs_entries)); // --------- @@ -71,7 +72,7 @@ "idmapd_domain": "example.com" ]; TEST (``( - Nfs::Import([ + Nfs::ImportAny([ global_options, entry1 ]) @@ -82,13 +83,14 @@ Assert::Equal("data.example.com:/mirror", Nfs::nfs_entries[0, "spec"]:""); DUMP("-- and Export"); - e = Nfs::Export(); - Assert::Equal(2, size(e)); - Assert::Equal(true, e[0, "enable_nfs4"]:false); - Assert::Equal("example.com", e[0, "idmapd_domain"]:""); - Assert::Equal("data.example.com:/mirror", e[1, "server_path"]:""); - Assert::Equal("/mirror", e[1, "mount_point"]:""); - Assert::Equal("defaults", e[1, "nfs_options"]:""); + ex = Nfs::Export(); + e = ex["nfs_entries"]:[]; + Assert::Equal(1, size(e)); + Assert::Equal(true, ex["enable_nfs4"]:false); + Assert::Equal("example.com", ex["idmapd_domain"]:""); + Assert::Equal("data.example.com:/mirror", e[0, "server_path"]:""); + Assert::Equal("/mirror", e[0, "mount_point"]:""); + Assert::Equal("defaults", e[0, "nfs_options"]:""); // --------- DUMP("- NFSv4 via vfstype"); @@ -103,7 +105,7 @@ ]; TEST (``( - Nfs::Import([ + Nfs::ImportAny([ global_options2, entry2 ]) @@ -115,13 +117,14 @@ Assert::Equal("data.example.com:/mirror", Nfs::nfs_entries[0, "spec"]:""); DUMP("-- and Export"); - e = Nfs::Export(); - Assert::Equal(2, size(e)); - Assert::Equal(true, e[0, "enable_nfs4"]:false); - Assert::Equal("example.com", e[0, "idmapd_domain"]:""); - Assert::Equal("data.example.com:/mirror", e[1, "server_path"]:""); - Assert::Equal("/mirror", e[1, "mount_point"]:""); - Assert::Equal("defaults", e[1, "nfs_options"]:""); + ex = Nfs::Export(); + e = ex["nfs_entries"]:[]; + Assert::Equal(1, size(e)); + Assert::Equal(true, ex["enable_nfs4"]:false); + Assert::Equal("example.com", ex["idmapd_domain"]:""); + Assert::Equal("data.example.com:/mirror", e[0, "server_path"]:""); + Assert::Equal("/mirror", e[0, "mount_point"]:""); + Assert::Equal("defaults", e[0, "nfs_options"]:""); // --------- DUMP("- with GSS"); @@ -131,7 +134,7 @@ "idmapd_domain": "example.com" ]; TEST (``( - Nfs::Import([ + Nfs::ImportAny([ global_options, entry1 ]) @@ -142,8 +145,9 @@ Assert::Equal("data.example.com:/mirror", Nfs::nfs_entries[0, "spec"]:""); DUMP("-- and Export"); - e = Nfs::Export(); - Assert::Equal(2, size(e)); - Assert::Equal(true, e[0, "enable_nfs_gss"]:false); - Assert::Equal("data.example.com:/mirror", e[1, "server_path"]:""); + ex = Nfs::Export(); + e = ex["nfs_entries"]:[]; + Assert::Equal(1, size(e)); + Assert::Equal(true, ex["enable_nfs_gss"]:false); + Assert::Equal("data.example.com:/mirror", e[0, "server_path"]:""); } From 44321324a96f8b7c9266f0bf40d55eaeb6b5745b Mon Sep 17 00:00:00 2001 From: Martin Vidner Date: Tue, 30 Jul 2013 09:57:42 +0200 Subject: [PATCH 45/50] moved Nfs::Options to NfsOptions y2r cannot handle it. I was too clever. Stupid me. --- src/Makefile.am | 12 +-- src/clients/nfs.ycp | 6 +- src/include/nfs/ui.ycp | 8 +- src/modules/Nfs.ycp | 4 +- .../{Nfs/Options.ycp => NfsOptions.ycp} | 2 +- testsuite/tests/nfs-options.out | 6 +- testsuite/tests/nfs-options.ycp | 82 +++++++++---------- yast2-nfs-client.spec.in | 5 +- 8 files changed, 57 insertions(+), 68 deletions(-) rename src/modules/{Nfs/Options.ycp => NfsOptions.ycp} (99%) diff --git a/src/Makefile.am b/src/Makefile.am index c38ea88..380f1a3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -16,18 +16,9 @@ myinclude_DATA = \ include/nfs/wizards.ycp module_DATA = \ + modules/NfsOptions.ycp \ modules/Nfs.ycp -nfs_moduledir = @moduledir@/Nfs -nfs_module_DATA = \ - modules/Nfs/Options.ycp - -nfs_modulebindir = $(nfs_moduledir) -nfs_modulebin_DATA = $(patsubst %.ycp,%.ybc,$(nfs_module_DATA)) - -# .dep does not work with subdirs -modules/Nfs.ybc: modules/Nfs/Options.ybc - desktop_DATA = nfs.desktop rncdir = $(schemadir)/autoyast/rnc @@ -48,4 +39,3 @@ check-local: version-check EXTRA_DIST = $(client_DATA) $(myinclude_DATA) $(module_DATA) $(nfs_module_DATA) $(desktop_DATA) $(rnc_DATA) include $(top_srcdir)/Makefile.am.common -ybcfiles += $(filter %.ybc,$(nfs_modulebin_DATA)) diff --git a/src/clients/nfs.ycp b/src/clients/nfs.ycp index 2bac723..f75c724 100644 --- a/src/clients/nfs.ycp +++ b/src/clients/nfs.ycp @@ -25,7 +25,7 @@ y2milestone ("----------------------------------------"); y2milestone ("NFS module started"); import "Nfs"; -import "Nfs::Options"; +import "NfsOptions"; import "Progress"; import "Report"; import "String"; @@ -87,7 +87,7 @@ boolean NfsAddHandler (map options) { if (! haskey (options, "mntops")) options["mntops"] = "defaults"; - string options_error = Nfs::Options::validate (options["mntops"]:""); + string options_error = NfsOptions::validate (options["mntops"]:""); if (size (options_error) > 0) { Report::Error (options_error); @@ -185,7 +185,7 @@ boolean NfsEditHandler (map options) { !CheckPath (mount) || IsMpInFstab (existing, mount)) return false; - string options_error = Nfs::Options::validate (entry["mntops"]:""); + string options_error = NfsOptions::validate (entry["mntops"]:""); if (size (options_error) > 0) { Report::Error (options_error); diff --git a/src/include/nfs/ui.ycp b/src/include/nfs/ui.ycp index 4317877..3b55cea 100644 --- a/src/include/nfs/ui.ycp +++ b/src/include/nfs/ui.ycp @@ -27,7 +27,7 @@ import "FileUtils"; import "Label"; import "Nfs"; - import "Nfs::Options"; + import "NfsOptions"; import "Popup"; import "SuSEFirewall"; import "Wizard"; @@ -211,7 +211,7 @@ mount = fstab_ent["file"]:""; nfs4 = fstab_ent["vfstype"]:"" == "nfs4"; options = fstab_ent["mntops"]:""; - nfs41 = nfs4 && Nfs::Options::get_nfs41 (options); + nfs41 = nfs4 && NfsOptions::get_nfs41 (options); servers = [ server ]; old = fstab_ent["spec"]:""; } @@ -385,10 +385,10 @@ which probably blocks the network scanning."); nfs4 = (boolean) UI::QueryWidget(`id(`nfs4), `Value); nfs41 = (boolean) UI::QueryWidget(`id(`nfs41), `Value); options = deletechars ((string) UI::QueryWidget(`id(`optionsent), `Value), " "); - options = Nfs::Options::set_nfs41(options, nfs41); + options = NfsOptions::set_nfs41(options, nfs41); ret = nil; - string options_error = Nfs::Options::validate (options); + string options_error = NfsOptions::validate (options); if (!CheckHostName (server)) { UI::SetFocus (`id (`serverent)); diff --git a/src/modules/Nfs.ycp b/src/modules/Nfs.ycp index eaf7d5d..2b54e07 100644 --- a/src/modules/Nfs.ycp +++ b/src/modules/Nfs.ycp @@ -23,7 +23,7 @@ import "FileUtils"; import "Mode"; - import "Nfs::Options"; + import "NfsOptions"; import "Report"; import "Service"; import "Summary"; @@ -552,7 +552,7 @@ the NFS client configuration.\n")); // check if options are valid if (size(options) > 0) { - if (Nfs::Options::validate(options) != "") + if (NfsOptions::validate(options) != "") { y2warning("invalid mount options: %1", options); return nil; diff --git a/src/modules/Nfs/Options.ycp b/src/modules/NfsOptions.ycp similarity index 99% rename from src/modules/Nfs/Options.ycp rename to src/modules/NfsOptions.ycp index 11ddc3c..cd039e2 100644 --- a/src/modules/Nfs/Options.ycp +++ b/src/modules/NfsOptions.ycp @@ -1,6 +1,6 @@ { -module "Nfs::Options"; +module "NfsOptions"; textdomain "nfs"; /** diff --git a/testsuite/tests/nfs-options.out b/testsuite/tests/nfs-options.out index 8e7172a..9e08680 100644 --- a/testsuite/tests/nfs-options.out +++ b/testsuite/tests/nfs-options.out @@ -1,4 +1,4 @@ -Dump Nfs::Options::validate +Dump NfsOptions::validate Return Empty option strings are not allowed. Return Return @@ -11,5 +11,5 @@ Return Empty value for option: 'rsize' Return Unknown option: 'two' Return Invalid option: 'retrans=trans=trans' Return Unknown option: 'intr' -Dump Nfs::Options::get_nfs41 -Dump Nfs::Options::set_nfs41 +Dump NfsOptions::get_nfs41 +Dump NfsOptions::set_nfs41 diff --git a/testsuite/tests/nfs-options.ycp b/testsuite/tests/nfs-options.ycp index 35742d6..8b48886 100644 --- a/testsuite/tests/nfs-options.ycp +++ b/testsuite/tests/nfs-options.ycp @@ -1,73 +1,73 @@ { include "testsuite.ycp"; - import "Nfs::Options"; + import "NfsOptions"; import "Assert"; - DUMP ("Nfs::Options::validate"); - TEST (``(Nfs::Options::validate ("")), [], nil); - TEST (``(Nfs::Options::validate ("defaults")), [], nil); - TEST (``(Nfs::Options::validate ("nolock,bg")), [], nil); - TEST (``(Nfs::Options::validate ("nolock,nobg")), [], nil); - TEST (``(Nfs::Options::validate ("nolock,rsize=8192")), [], nil); - TEST (``(Nfs::Options::validate ("nolock, bg")), [], nil); - TEST (``(Nfs::Options::validate ("nolock,unknownoption")), [], nil); - TEST (``(Nfs::Options::validate ("nolock,unknownassignment=true")), [], nil); - TEST (``(Nfs::Options::validate ("nolock,rsize=")), [], nil); - TEST (``(Nfs::Options::validate ("nolock,two=equal=signs")), [], nil); - TEST (``(Nfs::Options::validate ("nolock,retrans=trans=trans")), [], nil); - TEST (``(Nfs::Options::validate ("nolock,intr=bogus")), [], nil); + DUMP ("NfsOptions::validate"); + TEST (``(NfsOptions::validate ("")), [], nil); + TEST (``(NfsOptions::validate ("defaults")), [], nil); + TEST (``(NfsOptions::validate ("nolock,bg")), [], nil); + TEST (``(NfsOptions::validate ("nolock,nobg")), [], nil); + TEST (``(NfsOptions::validate ("nolock,rsize=8192")), [], nil); + TEST (``(NfsOptions::validate ("nolock, bg")), [], nil); + TEST (``(NfsOptions::validate ("nolock,unknownoption")), [], nil); + TEST (``(NfsOptions::validate ("nolock,unknownassignment=true")), [], nil); + TEST (``(NfsOptions::validate ("nolock,rsize=")), [], nil); + TEST (``(NfsOptions::validate ("nolock,two=equal=signs")), [], nil); + TEST (``(NfsOptions::validate ("nolock,retrans=trans=trans")), [], nil); + TEST (``(NfsOptions::validate ("nolock,intr=bogus")), [], nil); - DUMP ("Nfs::Options::get_nfs41"); - Assert::Equal(false, Nfs::Options::get_nfs41("")); - Assert::Equal(false, Nfs::Options::get_nfs41("defaults")); - Assert::Equal(false, Nfs::Options::get_nfs41("ro,sync")); - Assert::Equal(false, Nfs::Options::get_nfs41("minorversion=0")); - Assert::Equal(true, Nfs::Options::get_nfs41("minorversion=1")); + DUMP ("NfsOptions::get_nfs41"); + Assert::Equal(false, NfsOptions::get_nfs41("")); + Assert::Equal(false, NfsOptions::get_nfs41("defaults")); + Assert::Equal(false, NfsOptions::get_nfs41("ro,sync")); + Assert::Equal(false, NfsOptions::get_nfs41("minorversion=0")); + Assert::Equal(true, NfsOptions::get_nfs41("minorversion=1")); // "minorversion=2" does not exist yet, YAGNI - Assert::Equal(false, Nfs::Options::get_nfs41("subminorversion=1")); // substring must not match - // Assert::Equal(?, Nfs::Options::get_nfs41("minorversion=1,minorversion=0")); // don't care - Assert::Equal(false, Nfs::Options::get_nfs41("ro,minorversion=0,sync")); - Assert::Equal(true, Nfs::Options::get_nfs41("ro,minorversion=1,sync")); + Assert::Equal(false, NfsOptions::get_nfs41("subminorversion=1")); // substring must not match + // Assert::Equal(?, NfsOptions::get_nfs41("minorversion=1,minorversion=0")); // don't care + Assert::Equal(false, NfsOptions::get_nfs41("ro,minorversion=0,sync")); + Assert::Equal(true, NfsOptions::get_nfs41("ro,minorversion=1,sync")); - DUMP ("Nfs::Options::set_nfs41"); + DUMP ("NfsOptions::set_nfs41"); Assert::Equal( "", - Nfs::Options::set_nfs41("", false)); + NfsOptions::set_nfs41("", false)); Assert::Equal( "minorversion=1", - Nfs::Options::set_nfs41("", true)); + NfsOptions::set_nfs41("", true)); Assert::Equal( "defaults", - Nfs::Options::set_nfs41("defaults", false)); + NfsOptions::set_nfs41("defaults", false)); Assert::Equal( "minorversion=1", - Nfs::Options::set_nfs41("defaults", true)); + NfsOptions::set_nfs41("defaults", true)); Assert::Equal( "ro,sync", - Nfs::Options::set_nfs41("ro,sync", false)); + NfsOptions::set_nfs41("ro,sync", false)); Assert::Equal( "ro,sync,minorversion=1", - Nfs::Options::set_nfs41("ro,sync", true)); + NfsOptions::set_nfs41("ro,sync", true)); Assert::Equal( "minorversion=0", - Nfs::Options::set_nfs41("minorversion=0", false)); + NfsOptions::set_nfs41("minorversion=0", false)); Assert::Equal( "minorversion=1", - Nfs::Options::set_nfs41("minorversion=0", true)); + NfsOptions::set_nfs41("minorversion=0", true)); Assert::Equal( "defaults", - Nfs::Options::set_nfs41("minorversion=1", false)); + NfsOptions::set_nfs41("minorversion=1", false)); Assert::Equal( "minorversion=1", - Nfs::Options::set_nfs41("minorversion=1", true)); + NfsOptions::set_nfs41("minorversion=1", true)); Assert::Equal( "subminorversion=1", - Nfs::Options::set_nfs41("subminorversion=1", false)); + NfsOptions::set_nfs41("subminorversion=1", false)); Assert::Equal( "subminorversion=1,minorversion=1", - Nfs::Options::set_nfs41("subminorversion=1", true)); + NfsOptions::set_nfs41("subminorversion=1", true)); Assert::Equal( "ro,minorversion=0,sync", - Nfs::Options::set_nfs41("ro,minorversion=0,sync", false)); + NfsOptions::set_nfs41("ro,minorversion=0,sync", false)); Assert::Equal( "ro,sync,minorversion=1", - Nfs::Options::set_nfs41("ro,minorversion=0,sync", true)); + NfsOptions::set_nfs41("ro,minorversion=0,sync", true)); Assert::Equal( "ro,sync", - Nfs::Options::set_nfs41("ro,minorversion=1,sync", false)); + NfsOptions::set_nfs41("ro,minorversion=1,sync", false)); Assert::Equal( "ro,minorversion=1,sync", - Nfs::Options::set_nfs41("ro,minorversion=1,sync", true)); + NfsOptions::set_nfs41("ro,minorversion=1,sync", true)); } diff --git a/yast2-nfs-client.spec.in b/yast2-nfs-client.spec.in index d21eb4f..3d97d08 100644 --- a/yast2-nfs-client.spec.in +++ b/yast2-nfs-client.spec.in @@ -53,9 +53,8 @@ file system access. It allows access to files on remote machines. %dir @moduledir@ @moduledir@/Nfs.ycp @moduledir@/Nfs.ybc -%dir @moduledir@/Nfs -@moduledir@/Nfs/Options.ycp -@moduledir@/Nfs/Options.ybc +@moduledir@/NfsOptions.ycp +@moduledir@/NfsOptions.ybc %dir @desktopdir@ @desktopdir@/nfs.desktop %doc @docdir@ From f988c47cee1033aa03e9e679f20aba9a57e70d90 Mon Sep 17 00:00:00 2001 From: Martin Vidner Date: Tue, 30 Jul 2013 16:51:42 +0200 Subject: [PATCH 46/50] Fixed minor issues according to review. --- src/modules/Nfs.ycp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/modules/Nfs.ycp b/src/modules/Nfs.ycp index 2b54e07..2163b4f 100644 --- a/src/modules/Nfs.ycp +++ b/src/modules/Nfs.ycp @@ -98,16 +98,16 @@ } boolean ValidateAyNfsEntry(map entry) { - boolean missing = false; + boolean valid = true; foreach (string k, ["server_path", "mount_point", "nfs_options"], { if (! haskey (entry, k)) { y2error ("Missing at Import: '%1'.", k); - missing = true; + valid = false; } }); - return !missing; + return valid; } void GetOptionsAndEntriesSLE11(list settings, map & global_options, list > & entries) { @@ -139,7 +139,7 @@ GetOptionsAndEntriesSLE11((list) any_settings, global_options, entries); } else { - y2internal("Cannot happen, got neither a map nor a list"); + y2internal("Cannot happen, got neither a map nor a list: %1", any_settings); } } @@ -186,10 +186,10 @@ nfs_entries = maplist(map entry, entries, ``( $[ - "spec":entry["server_path"]:"", - "file":entry["mount_point"]:"", - "vfstype":entry["vfstype"]:"", - "mntops":entry["nfs_options"]:"" + "spec": entry["server_path"]:"", + "file": entry["mount_point"]:"", + "vfstype": entry["vfstype"]:"", + "mntops": entry["nfs_options"]:"" ] )); From be54246d9b7f75436d0e30bd3df084a84487ee47 Mon Sep 17 00:00:00 2001 From: Martin Vidner Date: Fri, 13 Sep 2013 13:48:34 +0200 Subject: [PATCH 47/50] yk restructure --- src/{ => autoyast-rnc}/nfs.rnc | 0 src/{ => desktop}/nfs.desktop | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename src/{ => autoyast-rnc}/nfs.rnc (100%) rename src/{ => desktop}/nfs.desktop (100%) diff --git a/src/nfs.rnc b/src/autoyast-rnc/nfs.rnc similarity index 100% rename from src/nfs.rnc rename to src/autoyast-rnc/nfs.rnc diff --git a/src/nfs.desktop b/src/desktop/nfs.desktop similarity index 100% rename from src/nfs.desktop rename to src/desktop/nfs.desktop From 045dbdb7a3db2b2a5d3aebf154d932c4ddf24620 Mon Sep 17 00:00:00 2001 From: Martin Vidner Date: Fri, 13 Sep 2013 13:49:22 +0200 Subject: [PATCH 48/50] yk patch actually had to apply the patch by hand, but that was easy --- testsuite/Makefile.am | 2 +- testsuite/tests/r-check.out | 7 +++++++ testsuite/tests/r-fstab.out | 6 ++++++ yast2-nfs-client.spec.in | 16 ++++++++-------- 4 files changed, 22 insertions(+), 9 deletions(-) diff --git a/testsuite/Makefile.am b/testsuite/Makefile.am index 3a56c02..40dc3df 100644 --- a/testsuite/Makefile.am +++ b/testsuite/Makefile.am @@ -6,7 +6,7 @@ export Y2DIR = $(top_srcdir)/src AUTOMAKE_OPTIONS = dejagnu -EXTRA_DIST = $(wildcard tests/*.out) $(wildcard tests/*.err) $(wildcard tests/*.ycp) $(wildcard tests/*.yh) +EXTRA_DIST = $(wildcard tests/*.out) $(wildcard tests/*.err) $(wildcard tests/*.rb) testsuite_prepare = @ydatadir@/testsuite/Makefile.testsuite diff --git a/testsuite/tests/r-check.out b/testsuite/tests/r-check.out index a5f55b3..f134acf 100644 --- a/testsuite/tests/r-check.out +++ b/testsuite/tests/r-check.out @@ -1,16 +1,23 @@ Dump CheckHostName Return true +Log The hostname entered is invalid. It must be Return false +Log The hostname entered is invalid. It must be Return false +Log The hostname entered is invalid. It must be Return false Return true +Log The hostname entered is invalid. It must be Return false Return true +Log The hostname entered is invalid. It must be Return false Return true +Log The hostname entered is invalid. It must be Return false Return true Return true +Log The hostname entered is invalid. It must be Return false Dump FormatHostnameForFstab Return [::1] diff --git a/testsuite/tests/r-fstab.out b/testsuite/tests/r-fstab.out index 6ac7d37..6483d81 100644 --- a/testsuite/tests/r-fstab.out +++ b/testsuite/tests/r-fstab.out @@ -1,12 +1,18 @@ Dump FstabTableItems Return [`item (`id (0), "foo.bar.com ", "/home ", "/home ", "nfs4", "defaults "), `item (`id (1), "foo.bar.com ", "/var/spool/mail ", "/var/spool/mail ", "nfs", "defaults "), `item (`id (2), "foo.bar.com.tw ", "/local/install ", "/install ", "nfs", "hard,intr ")] Dump IsMpInFstab +Log fstab already contains an entry Return true +Log fstab already contains an entry Return true Return false Dump CheckPath +Log The path entered is invalid. Return false +Log The path entered is invalid. Return false +Log The path entered is invalid. Return false +Log The path entered is invalid. Return false Return true diff --git a/yast2-nfs-client.spec.in b/yast2-nfs-client.spec.in index 3d97d08..b895cd8 100644 --- a/yast2-nfs-client.spec.in +++ b/yast2-nfs-client.spec.in @@ -26,6 +26,8 @@ Provides: yast2-config-network:/usr/lib/YaST2/clients/lan_nfs_client.ycp BuildArch: noarch +Requires: yast2-ruby-bindings >= 1.0.0 + Summary: YaST2 - NFS Configuration Url: http://en.opensuse.org/Portal:YaST @@ -46,15 +48,13 @@ file system access. It allows access to files on remote machines. %dir @yncludedir@/nfs @yncludedir@/nfs/* %dir @clientdir@ -@clientdir@/nfs.ycp -@clientdir@/nfs-client.ycp -@clientdir@/nfs_auto.ycp -@clientdir@/nfs-client4part.ycp +@clientdir@/nfs.rb +@clientdir@/nfs-client.rb +@clientdir@/nfs_auto.rb +@clientdir@/nfs-client4part.rb %dir @moduledir@ -@moduledir@/Nfs.ycp -@moduledir@/Nfs.ybc -@moduledir@/NfsOptions.ycp -@moduledir@/NfsOptions.ybc +@moduledir@/Nfs.rb +@moduledir@/NfsOptions.rb %dir @desktopdir@ @desktopdir@/nfs.desktop %doc @docdir@ From ccde9a1ce52c4125394f60d959c87d74b607a053 Mon Sep 17 00:00:00 2001 From: Martin Vidner Date: Fri, 13 Sep 2013 13:50:27 +0200 Subject: [PATCH 49/50] yk ruby --- src/clients/nfs-client.rb | 15 + src/clients/nfs-client.ycp | 9 - src/clients/nfs-client4part.rb | 99 ++++ src/clients/nfs-client4part.ycp | 90 ---- src/clients/nfs.rb | 368 +++++++++++++++ src/clients/nfs.ycp | 314 ------------- src/clients/nfs_auto.rb | 114 +++++ src/clients/nfs_auto.ycp | 111 ----- src/include/nfs/routines.rb | 197 ++++++++ src/include/nfs/routines.ycp | 189 -------- src/include/nfs/ui.rb | 738 +++++++++++++++++++++++++++++ src/include/nfs/ui.ycp | 731 ----------------------------- src/include/nfs/wizards.rb | 54 +++ src/include/nfs/wizards.ycp | 67 --- src/modules/Nfs.rb | 789 ++++++++++++++++++++++++++++++++ src/modules/Nfs.ycp | 753 ------------------------------ src/modules/NfsOptions.rb | 211 +++++++++ src/modules/NfsOptions.ycp | 147 ------ testsuite/tests/autoyast.rb | 155 +++++++ testsuite/tests/autoyast.ycp | 153 ------- testsuite/tests/escape.rb | 65 +++ testsuite/tests/escape.ycp | 63 --- testsuite/tests/nfs-options.rb | 96 ++++ testsuite/tests/nfs-options.ycp | 73 --- testsuite/tests/r-check.rb | 62 +++ testsuite/tests/r-check.ycp | 54 --- testsuite/tests/r-fstab.rb | 79 ++++ testsuite/tests/r-fstab.ycp | 71 --- testsuite/tests/r-spec.rb | 35 ++ testsuite/tests/r-spec.ycp | 27 -- testsuite/tests/r-strip.rb | 32 ++ testsuite/tests/r-strip.ycp | 24 - testsuite/tests/readwrite.rb | 133 ++++++ testsuite/tests/readwrite.ycp | 155 ------- testsuite/tests/readwrite2.rb | 222 +++++++++ testsuite/tests/readwrite2.ycp | 237 ---------- 36 files changed, 3464 insertions(+), 3268 deletions(-) create mode 100644 src/clients/nfs-client.rb delete mode 100644 src/clients/nfs-client.ycp create mode 100644 src/clients/nfs-client4part.rb delete mode 100644 src/clients/nfs-client4part.ycp create mode 100644 src/clients/nfs.rb delete mode 100644 src/clients/nfs.ycp create mode 100644 src/clients/nfs_auto.rb delete mode 100644 src/clients/nfs_auto.ycp create mode 100644 src/include/nfs/routines.rb delete mode 100644 src/include/nfs/routines.ycp create mode 100644 src/include/nfs/ui.rb delete mode 100644 src/include/nfs/ui.ycp create mode 100644 src/include/nfs/wizards.rb delete mode 100644 src/include/nfs/wizards.ycp create mode 100644 src/modules/Nfs.rb delete mode 100644 src/modules/Nfs.ycp create mode 100644 src/modules/NfsOptions.rb delete mode 100644 src/modules/NfsOptions.ycp create mode 100644 testsuite/tests/autoyast.rb delete mode 100644 testsuite/tests/autoyast.ycp create mode 100644 testsuite/tests/escape.rb delete mode 100644 testsuite/tests/escape.ycp create mode 100644 testsuite/tests/nfs-options.rb delete mode 100644 testsuite/tests/nfs-options.ycp create mode 100644 testsuite/tests/r-check.rb delete mode 100644 testsuite/tests/r-check.ycp create mode 100644 testsuite/tests/r-fstab.rb delete mode 100644 testsuite/tests/r-fstab.ycp create mode 100644 testsuite/tests/r-spec.rb delete mode 100644 testsuite/tests/r-spec.ycp create mode 100644 testsuite/tests/r-strip.rb delete mode 100644 testsuite/tests/r-strip.ycp create mode 100644 testsuite/tests/readwrite.rb delete mode 100644 testsuite/tests/readwrite.ycp create mode 100644 testsuite/tests/readwrite2.rb delete mode 100644 testsuite/tests/readwrite2.ycp diff --git a/src/clients/nfs-client.rb b/src/clients/nfs-client.rb new file mode 100644 index 0000000..56ab273 --- /dev/null +++ b/src/clients/nfs-client.rb @@ -0,0 +1,15 @@ +# encoding: utf-8 + +# Author: Martin Vidner +# Summary: Just a redirection +# $Id$ +module Yast + class NfsClientClient < Client + def main + @target = "nfs" + WFM.CallFunction(@target, WFM.Args) + end + end +end + +Yast::NfsClientClient.new.main diff --git a/src/clients/nfs-client.ycp b/src/clients/nfs-client.ycp deleted file mode 100644 index f218f5d..0000000 --- a/src/clients/nfs-client.ycp +++ /dev/null @@ -1,9 +0,0 @@ -/** - * Author: Martin Vidner - * Summary: Just a redirection - * $Id$ - */ -{ - string target = "nfs"; - return WFM::CallFunction (target, WFM::Args ()); -} diff --git a/src/clients/nfs-client4part.rb b/src/clients/nfs-client4part.rb new file mode 100644 index 0000000..8e089a5 --- /dev/null +++ b/src/clients/nfs-client4part.rb @@ -0,0 +1,99 @@ +# encoding: utf-8 + +# File: clients/ +# Summary: nfs-client stuff made accesible from +# Author: Bubli +# +module Yast + class NfsClient4partClient < Client + def main + Yast.import "UI" + textdomain "nfs" + + Yast.import "Nfs" + Yast.import "Wizard" + Yast.include self, "nfs/ui.rb" + + # y2milestone("----------------------------------------"); + # y2milestone("Nfs client proposal started"); + # y2milestone("Arguments: %1", WFM::Args()); + + @ret = nil + @func = "" + @param = {} + + if Ops.greater_than(Builtins.size(WFM.Args), 0) && + Ops.is_string?(WFM.Args(0)) + @func = Convert.to_string(WFM.Args(0)) + if Ops.greater_than(Builtins.size(WFM.Args), 1) && + Ops.is_map?(WFM.Args(1)) + @param = Convert.to_map(WFM.Args(1)) + end + end + + if @func == "CreateUI" + Wizard.SetHelpText(@help_text1) + return MainDialogLayout() + elsif @func == "FromStorage" + @shares = Ops.get_list(@param, "shares", []) + + Nfs.nfs_entries = Builtins.maplist(@shares) do |entry| + { + "spec" => Ops.get_string(entry, "device", ""), + "file" => Ops.get_string(entry, "mount", ""), + "vfstype" => Ops.get_symbol(entry, "used_fs", :nfs) == :nfs ? "nfs" : "nfs4", + "mntops" => Ops.get_string(entry, "fstopt", "") + } + end + Builtins.y2milestone( + "Nfs shares imported from storage %1", + Nfs.nfs_entries + ) + @nfs_entries = deep_copy(Nfs.nfs_entries) + InitFstabEntries() + elsif @func == "Read" + Nfs.skip_fstab = true + Nfs.Read + elsif @func == "HandleEvent" + @widget_id = Ops.get(@param, "widget_id") + @w_ids = [:newbut, :editbut, :delbut] + + HandleEvent(@widget_id) + Builtins.y2milestone("%1", @modify_line) + Nfs.nfs_entries = deep_copy(@nfs_entries) + + if Builtins.contains(@w_ids, Convert.to_symbol(@widget_id)) + return ToStorage(@modify_line) + else + return nil + end + end + + nil + end + + def ToStorage(entry) + entry = deep_copy(entry) + ret = {} + + if entry != nil && entry != {} + ret = { + "device" => Ops.get_string(entry, "spec", ""), + "mount" => Ops.get_string(entry, "file", ""), + "fstopt" => Ops.get_string(entry, "mntops", ""), + "vfstype" => Ops.get_string(entry, "vfstype", "nfs") + } + if Builtins.haskey(entry, "old") + ret = Builtins.add( + ret, + "old_device", + Ops.get_string(entry, "old", "") + ) + end + end + deep_copy(ret) + end + end +end + +Yast::NfsClient4partClient.new.main diff --git a/src/clients/nfs-client4part.ycp b/src/clients/nfs-client4part.ycp deleted file mode 100644 index 31c6d48..0000000 --- a/src/clients/nfs-client4part.ycp +++ /dev/null @@ -1,90 +0,0 @@ -/** - * File: clients/ - * Summary: nfs-client stuff made accesible from - * Author: Bubli - * - */ - -{ - textdomain "nfs"; - - import "Nfs"; - import "Wizard"; - include "nfs/ui.ycp"; - - /*y2milestone("----------------------------------------"); - y2milestone("Nfs client proposal started"); - y2milestone("Arguments: %1", WFM::Args());*/ - - any ret = nil; - string func = ""; - map param = $[]; - - if(size(WFM::Args()) > 0 && is(WFM::Args(0), string)) { - func = (string)WFM::Args(0); - if(size(WFM::Args()) > 1 && is(WFM::Args(1), map)) - param = (map)WFM::Args(1); - } - - map ToStorage ( map entry ) - { - map ret = $[]; - - if (entry != nil && entry != $[]) - { - ret = $[ - "device" : entry["spec"]:"", - "mount" : entry["file"]:"", - "fstopt" : entry["mntops"]:"", - "vfstype" : entry["vfstype"]:"nfs" - ]; - if (haskey ( entry, "old" )) - ret = add(ret, "old_device" , entry["old"]:"" ); - } - return ret; - } - - if (func == "CreateUI") - { - Wizard::SetHelpText( help_text1 ); - return MainDialogLayout(); - } - - else if ( func == "FromStorage" ) - { - list > shares = ( list < map >) param["shares"]:[]; - - Nfs::nfs_entries = maplist( map entry, shares, { - return ( $[ - "spec" : entry["device"]:"", - "file" : entry["mount"]:"", - "vfstype" : entry["used_fs"]:`nfs == `nfs ? "nfs" : "nfs4", - "mntops": entry["fstopt"]:"" - ]); - }); - y2milestone("Nfs shares imported from storage %1", Nfs::nfs_entries); - nfs_entries = Nfs::nfs_entries; - InitFstabEntries(); - - } - else if (func == "Read") - { - Nfs::skip_fstab = true; - Nfs::Read(); - } - else if (func == "HandleEvent") - { - any widget_id = param["widget_id"]:nil; - list w_ids = [ `newbut, `editbut, `delbut ]; - - HandleEvent( widget_id); - y2milestone("%1", modify_line); - Nfs::nfs_entries = nfs_entries; - - if ( contains( w_ids, (symbol) widget_id )) - return ToStorage( modify_line ); - else - return nil; - } - -} diff --git a/src/clients/nfs.rb b/src/clients/nfs.rb new file mode 100644 index 0000000..9636ae3 --- /dev/null +++ b/src/clients/nfs.rb @@ -0,0 +1,368 @@ +# encoding: utf-8 + +# File: clients/nfs.ycp +# Package: Configuration of NFS +# Summary: Main file +# Authors: +# Jan Holesovsky +# Dan Vesely +# Martin Vidner +# +# $Id$ +# +# Main file for nfs configuration. Uses all other files. +module Yast + class NfsClient < Client + def main + Yast.import "UI" + + #** + #

Configuration of NFS

+ + textdomain "nfs" + + # The main () + Builtins.y2milestone("----------------------------------------") + Builtins.y2milestone("NFS module started") + + Yast.import "Nfs" + Yast.import "NfsOptions" + Yast.import "Progress" + Yast.import "Report" + Yast.import "String" + Yast.import "Summary" + + Yast.import "CommandLine" + + Yast.include self, "nfs/wizards.rb" + + @cmdline_description = { + "id" => "nfs", + # Command line help text for the nfs module + "help" => _( + "Configuration of NFS client" + ), + "guihandler" => fun_ref(method(:NfsSequence), "any ()"), + "initialize" => fun_ref(Nfs.method(:Read), "boolean ()"), + "finish" => fun_ref(Nfs.method(:Write), "boolean ()"), + "actions" => { + "list" => { + # TODO summary is probably better... + "handler" => fun_ref( + method(:NfsListHandler), + "boolean (map)" + ), + # command line action help + "help" => _( + "List configured NFS mounts" + ) + }, + "add" => { + "handler" => fun_ref(method(:NfsAddHandler), "boolean (map)"), + # command line action help + "help" => _("Add an NFS mount") + }, + "edit" => { + "handler" => fun_ref(method(:NfsEditHandler), "boolean (map)"), + # command line action help + "help" => _("Edit an NFS mount") + }, + "delete" => { + "handler" => fun_ref(method(:NfsDeleteHandler), "boolean (map)"), + # command line action help + "help" => _("Delete an NFS mount") + } + }, + "options" => { + # TODO adjust names? create comaptibility aliases? + "spec" => { + "type" => "string", + # host:path + # command line option help + # fstab(5): fs_spec + "help" => _( + "Remote file system (in the form 'host:path')" + ) + }, + "file" => { + "type" => "string", + # path + # command line option help + # fstab(5): fs_file + "help" => _( + "Local mount point" + ) + }, + # use defaults when not specified? describe in help? + "mntops" => { + "type" => "string", + # a list? + # command line option help + # fstab(5): fs_mntops + "help" => _( + "Mount options" + ) + }, + "type" => { + "type" => "string", + # nfs or nfs4 + # command line option help + # fstab(5): fs_type + "help" => _( + "File system ID, supported nfs and nfs4. Default value is nfs." + ) + } + }, + "mappings" => { + "list" => [], + "add" => ["spec", "file", "mntops", "type"], + # either of spec and file is key + "edit" => [ + "spec", + "file", + "mntops", + "type" + ], + # either of spec and file is key + "delete" => ["spec", "file"] + } + } + + # main ui function + @ret = nil + + @ret = CommandLine.Run(@cmdline_description) + Builtins.y2debug("ret=%1", @ret) + + # Finish + Builtins.y2milestone("NFS module finished") + Builtins.y2milestone("----------------------------------------") + + deep_copy(@ret) + + # EOF + end + + # CLI action handler. + # Print summary in command line + # @param [Hash] options command options + # @return false so that Write is not called in non-interactive mode + def NfsListHandler(options) + options = deep_copy(options) + nfs_entries = deep_copy(Nfs.nfs_entries) + if Ops.less_than(Builtins.size(nfs_entries), 1) + CommandLine.Print(Summary.NotConfigured) + return false + end + items = [] + Builtins.foreach(FstabTableItems(nfs_entries)) do |i| + items = Builtins.add( + items, + [ + Ops.get_string(i, 1, ""), + Ops.get_string(i, 2, ""), + Ops.get_string(i, 3, ""), + Ops.get_string(i, 4, "") + ] + ) + end + + CommandLine.Print( + String.TextTable( + [ + _("Server") + " ", + _("Remote File System") + " ", + _("Mount Point") + " ", + _("Options") + " " + ], + items, + {} + ) + ) + false + end + + # CLI action handler. + # @param [Hash] options command options + # @return whether successful + def NfsAddHandler(options) + options = deep_copy(options) + nfs_entries = deep_copy(Nfs.nfs_entries) + + specl = Builtins.splitstring(Ops.get_string(options, "spec", ""), ":") + server = Ops.get_string(specl, 0, "") + pth = Ops.get_string(specl, 1, "") + mount = Ops.get_string(options, "file", "") + existing = Convert.convert( + Builtins.union(Nfs.non_nfs_entries, nfs_entries), + :from => "list", + :to => "list " + ) + + if !CheckHostName(server) || !CheckPath(pth) || !CheckPath(mount) || + IsMpInFstab(existing, mount) + return false + end + + if !Builtins.haskey(options, "mntops") + Ops.set(options, "mntops", "defaults") + end + + options_error = NfsOptions.validate(Ops.get_string(options, "mntops", "")) + if Ops.greater_than(Builtins.size(options_error), 0) + Report.Error(options_error) + return false + end + + type = Ops.get_string(options, "type", "nfs") + if type != "nfs" && type != "nfs4" + Report.Error(_("Unknown value for option \"type\".")) + return false + end + Ops.set(options, "vfstype", type) + + nfs_entries = Builtins.add( + nfs_entries, + Convert.convert(options, :from => "map", :to => "map ") + ) + Nfs.nfs_entries = deep_copy(nfs_entries) + true + end + + # CLI action handler. + # @param [Hash] options command options + # @return whether successful + def NfsEditHandler(options) + options = deep_copy(options) + nfs_entries = deep_copy(Nfs.nfs_entries) + + spec = Ops.get_string(options, "spec", "") + file = Ops.get_string(options, "file", "") + + if spec == "" && file == "" + # error + CommandLine.Print(_("No NFS mount specified.")) + return false + end + + type = Ops.get_string(options, "type", "nfs") + if type != "nfs" && type != "nfs4" + Report.Error(_("Unknown value for option \"type\".")) + return false + end + Ops.set(options, "vfstype", type) if Builtins.haskey(options, "type") + + entries = [] + i = 0 + Builtins.foreach(nfs_entries) do |entry2| + if Ops.get_string(entry2, "spec", "") == spec || + Ops.get_string(entry2, "file", "") == file + entries = Builtins.add(entries, i) + Builtins.y2internal("to change: %1", entry2) + end + i = Ops.add(i, 1) + end + if Builtins.size(entries) == 0 + # error message + CommandLine.Print(_("No NFS mount matching the criteria found.")) + return false + end + if Ops.greater_than(Builtins.size(entries), 1) + items = [] + Builtins.foreach(FstabTableItems(nfs_entries)) do |i2| + items = Builtins.add( + items, + [ + Ops.get_string(i2, 1, ""), + Ops.get_string(i2, 2, ""), + Ops.get_string(i2, 3, ""), + Ops.get_string(i2, 4, "") + ] + ) + end + + # error message + CommandLine.Print(_("Multiple NFS mounts match the criteria:")) + Builtins.foreach(entries) do |e| + entry2 = Ops.get(nfs_entries, e, {}) + CommandLine.Print( + Builtins.sformat( + "spec=%1, file=%2", + Ops.get_string(entry2, "spec", ""), + Ops.get_string(entry2, "file", "") + ) + ) + end + return false + end + + # now edit existing entry and check the validity + entryno = Ops.get(entries, 0, 0) + entry = Builtins.union(Ops.get(nfs_entries, entryno, {}), options) + + specl = Builtins.splitstring(Ops.get_string(entry, "spec", ""), ":") + server = Ops.get_string(specl, 0, "") + pth = Ops.get_string(specl, 1, "") + mount = Ops.get_string(entry, "file", "") + existing = Convert.convert( + Builtins.union( + Nfs.non_nfs_entries, + Builtins.remove(nfs_entries, entryno) + ), + :from => "list", + :to => "list " + ) + + if !CheckHostName(server) || !CheckPath(pth) || !CheckPath(mount) || + IsMpInFstab(existing, mount) + return false + end + + options_error = NfsOptions.validate(Ops.get_string(entry, "mntops", "")) + if Ops.greater_than(Builtins.size(options_error), 0) + Report.Error(options_error) + return false + end + + Ops.set( + nfs_entries, + entryno, + Convert.convert(entry, :from => "map", :to => "map ") + ) + Nfs.nfs_entries = deep_copy(nfs_entries) + true + end + + # CLI action handler. + # @param [Hash] options command options + # @return whether successful + def NfsDeleteHandler(options) + options = deep_copy(options) + nfs_entries = deep_copy(Nfs.nfs_entries) + + spec = Ops.get_string(options, "spec", "") + file = Ops.get_string(options, "file", "") + + if spec == "" && file == "" + # error + CommandLine.Print(_("No NFS mount specified.")) + return false + end + deleted = false + nfs_entries = Builtins.filter(nfs_entries) do |entry| + if spec != "" && Ops.get_string(entry, "spec", "") != spec || + file != "" && Ops.get_string(entry, "file", "") != file + next true + else + deleted = true + next false + end + end + + Nfs.nfs_entries = deep_copy(nfs_entries) + deleted + end + end +end + +Yast::NfsClient.new.main diff --git a/src/clients/nfs.ycp b/src/clients/nfs.ycp deleted file mode 100644 index f75c724..0000000 --- a/src/clients/nfs.ycp +++ /dev/null @@ -1,314 +0,0 @@ -/** - * File: clients/nfs.ycp - * Package: Configuration of NFS - * Summary: Main file - * Authors: - * Jan Holesovsky - * Dan Vesely - * Martin Vidner - * - * $Id$ - * - * Main file for nfs configuration. Uses all other files. - */ - -{ - -/*** - *

Configuration of NFS

- */ - -textdomain "nfs"; - -/* The main () */ -y2milestone ("----------------------------------------"); -y2milestone ("NFS module started"); - -import "Nfs"; -import "NfsOptions"; -import "Progress"; -import "Report"; -import "String"; -import "Summary"; - -import "CommandLine"; - -include "nfs/wizards.ycp"; - -/** - * CLI action handler. - * Print summary in command line - * @param options command options - * @return false so that Write is not called in non-interactive mode - */ -boolean NfsListHandler (map options) { - - - list > nfs_entries = Nfs::nfs_entries; - if (size (nfs_entries) < 1) - { - CommandLine::Print (Summary::NotConfigured ()); - return false; - } - list > items = []; - foreach (term i, FstabTableItems (nfs_entries), { - items = add (items, [i[1]:"", i[2]:"", i[3]:"", i[4]:""]); - }); - - CommandLine::Print (String::TextTable ([ - _("Server")+" ", - _("Remote File System")+" ", - _("Mount Point")+" ", - _("Options")+" " - ], items, $[]) - ); - return false; -} - -/** - * CLI action handler. - * @param options command options - * @return whether successful - */ -boolean NfsAddHandler (map options) { - - list > nfs_entries = Nfs::nfs_entries; - - list specl = splitstring (options["spec"]:"", ":"); - string server = specl[0]:""; - string pth = specl[1]:""; - string mount = options["file"]:""; - list existing = (list) union (Nfs::non_nfs_entries, nfs_entries); - - if (!CheckHostName (server) || !CheckPath (pth) || - !CheckPath (mount) || IsMpInFstab (existing, mount)) - return false; - - if (! haskey (options, "mntops")) - options["mntops"] = "defaults"; - - string options_error = NfsOptions::validate (options["mntops"]:""); - if (size (options_error) > 0) - { - Report::Error (options_error); - return false; - } - - string type = options["type"]:"nfs"; - if (type != "nfs" && type != "nfs4") - { - Report::Error (_("Unknown value for option \"type\".")); - return false; - } - options["vfstype"] = type; - - nfs_entries = add (nfs_entries, (map) options); - Nfs::nfs_entries = nfs_entries; - return true; -} - -/** - * CLI action handler. - * @param options command options - * @return whether successful - */ -boolean NfsEditHandler (map options) { - - list > nfs_entries = Nfs::nfs_entries; - - string spec = options["spec"]:""; - string file = options["file"]:""; - - if (spec == "" && file == "") - { - // error - CommandLine::Print (_("No NFS mount specified.")); - return false; - } - - string type = options["type"]:"nfs"; - if (type != "nfs" && type != "nfs4") - { - Report::Error (_("Unknown value for option \"type\".")); - return false; - } - if (haskey(options,"type")) - { - options["vfstype"] = type; - } - - list entries = []; - integer i = 0; - foreach (map entry, nfs_entries, { - if (entry["spec"]:"" == spec || entry["file"]:"" == file) - { - entries = add (entries, i); - y2internal ("to change: %1", entry); - } - i = i + 1; - }); - if (size (entries) == 0) - { - // error message - CommandLine::Print (_("No NFS mount matching the criteria found.")); - return false; - } - if (size (entries) > 1) - { - list > items = []; - foreach (term i, FstabTableItems (nfs_entries), { - items = add (items, [i[1]:"", i[2]:"", i[3]:"", i[4]:""]); - }); - - // error message - CommandLine::Print (_("Multiple NFS mounts match the criteria:")); - foreach (integer e, entries, { - map entry = nfs_entries[e]:$[]; - CommandLine::Print ( - sformat("spec=%1, file=%2", entry["spec"]:"",entry["file"]:"")); - }); - return false; - } - - // now edit existing entry and check the validity - integer entryno = entries[0]:0; - map entry = union (nfs_entries[entryno]:$[], options); - - list specl = splitstring (entry["spec"]:"", ":"); - string server = specl[0]:""; - string pth = specl[1]:""; - string mount = entry["file"]:""; - list existing = (list) - union (Nfs::non_nfs_entries, remove (nfs_entries, entryno)); - - if (!CheckHostName (server) || !CheckPath (pth) || - !CheckPath (mount) || IsMpInFstab (existing, mount)) - return false; - - string options_error = NfsOptions::validate (entry["mntops"]:""); - if (size (options_error) > 0) - { - Report::Error (options_error); - return false; - } - - nfs_entries[entryno] = (map) entry; - Nfs::nfs_entries = nfs_entries; - return true; -} - -/** - * CLI action handler. - * @param options command options - * @return whether successful - */ -boolean NfsDeleteHandler (map options) { - - list > nfs_entries = Nfs::nfs_entries; - - string spec = options["spec"]:""; - string file = options["file"]:""; - - if (spec == "" && file == "") - { - // error - CommandLine::Print (_("No NFS mount specified.")); - return false; - } - boolean deleted = false; - nfs_entries = filter (map entry, nfs_entries, { - if ((spec != "" && entry["spec"]:"" != spec) || - (file != "" && entry["file"]:"" != file)) - return true; - else - { - deleted = true; - return false; - } - }); - - Nfs::nfs_entries = nfs_entries; - return deleted; -} - -map cmdline_description = $[ - "id" : "nfs", - /* Command line help text for the nfs module */ - "help" : _("Configuration of NFS client"), - "guihandler" : NfsSequence, - "initialize" : Nfs::Read, - "finish" : Nfs::Write, - "actions" : $[ - "list" : $[ // TODO summary is probably better... - "handler" : NfsListHandler, - // command line action help - "help" : _("List configured NFS mounts"), - ], - "add" : $[ - "handler" : NfsAddHandler, - // command line action help - "help" : _("Add an NFS mount"), - ], - "edit" : $[ - "handler" : NfsEditHandler, - // command line action help - "help" : _("Edit an NFS mount"), - ], - "delete" : $[ - "handler" : NfsDeleteHandler, - // command line action help - "help" : _("Delete an NFS mount"), - ], - ], - "options" : $[ - // TODO adjust names? create comaptibility aliases? - "spec" : $[ - "type" : "string", // host:path - // command line option help - // fstab(5): fs_spec - "help" : _("Remote file system (in the form 'host:path')"), - ], - "file" : $[ - "type" : "string", // path - // command line option help - // fstab(5): fs_file - "help" : _("Local mount point"), - ], - // use defaults when not specified? describe in help? - "mntops" : $[ - "type" : "string", // a list? - // command line option help - // fstab(5): fs_mntops - "help" : _("Mount options"), - ], - "type" : $[ - "type" : "string", // nfs or nfs4 - // command line option help - // fstab(5): fs_type - "help" : _("File system ID, supported nfs and nfs4. Default value is nfs."), - ], - ], - "mappings" : $[ - "list" : [], - "add" : ["spec", "file", "mntops","type",], - // either of spec and file is key - "edit" : ["spec", "file", "mntops","type",], - // either of spec and file is key - "delete" : ["spec", "file",], - ] -]; - -/* main ui function */ -any ret = nil; - -ret = CommandLine::Run(cmdline_description); -y2debug("ret=%1", ret); - -/* Finish */ -y2milestone("NFS module finished"); -y2milestone("----------------------------------------"); - -return ret; - -/* EOF */ -} diff --git a/src/clients/nfs_auto.rb b/src/clients/nfs_auto.rb new file mode 100644 index 0000000..be11307 --- /dev/null +++ b/src/clients/nfs_auto.rb @@ -0,0 +1,114 @@ +# encoding: utf-8 + +# File: +# nfs_auto.ycp +# +# Package: +# Configuration of NFS client +# +# Summary: +# Client for autoinstallation +# +# Authors: +# Martin Vidner +# +# $Id$ +# +# This is a client for autoinstallation. It takes its arguments, +# goes through the configuration and return the setting. +# Does not do any changes to the configuration. + +# @param first a map of mail settings +# @return [Hash] edited settings or empty map if canceled +# @example map mm = $[ "FAIL_DELAY" : "77" ]; +# @example map ret = WFM::CallModule ("mail_auto", [ mm ]); +module Yast + class NfsAutoClient < Client + def main + Yast.import "UI" + textdomain "nfs" + + Builtins.y2milestone("----------------------------------------") + Builtins.y2milestone("Nfs auto started") + + Yast.import "Nfs" + Yast.import "Wizard" + Yast.include self, "nfs/ui.rb" + + @ret = nil + @func = "" + @param = {} + + # Check arguments + if Ops.greater_than(Builtins.size(WFM.Args), 0) && + Ops.is_string?(WFM.Args(0)) + @func = Convert.to_string(WFM.Args(0)) + if Ops.greater_than(Builtins.size(WFM.Args), 1) && + Ops.is_map?(WFM.Args(1)) + @param = Convert.convert( + WFM.Args(1), + :from => "any", + :to => "map " + ) + end + if Ops.greater_than(Builtins.size(WFM.Args), 1) && + Ops.is_list?(WFM.Args(1)) + Builtins.y2warning( + "Old-style configuration detected (got list, expected map). section needs to be converted to match up-to-date schema" + ) + end + end + Builtins.y2debug("func=%1", @func) + Builtins.y2debug("param=%1", @param) + + # Create a summary + if @func == "Import" + @ret = Nfs.Import(@param) + # Create a summary + elsif @func == "Summary" + @ret = Nfs.Summary + # Reset configuration + elsif @func == "Reset" + Nfs.Import({}) + @ret = {} + # Change configuration (run AutoSequence) + elsif @func == "Change" + Wizard.CreateDialog + Wizard.SetDesktopIcon("nfs") + @ret = FstabDialog() + UI.CloseDialog + elsif @func == "GetModified" + @ret = Nfs.GetModified + elsif @func == "SetModified" + Nfs.SetModified + # Return actual state + elsif @func == "Packages" + @ret = Nfs.AutoPackages + # Return actual state + elsif @func == "Export" + @ret = Nfs.Export + elsif @func == "Read" + @ret = Nfs.Read + # Write givven settings + elsif @func == "Write" + Yast.import "Progress" + @progress_orig = Progress.set(false) + @ret = Nfs.WriteOnly + Progress.set(@progress_orig) + else + Builtins.y2error("Unknown function: %1", @func) + @ret = false + end + + Builtins.y2debug("ret=%1", @ret) + Builtins.y2milestone("Nfs auto finished") + Builtins.y2milestone("----------------------------------------") + + deep_copy(@ret) + + # EOF + end + end +end + +Yast::NfsAutoClient.new.main diff --git a/src/clients/nfs_auto.ycp b/src/clients/nfs_auto.ycp deleted file mode 100644 index 4257902..0000000 --- a/src/clients/nfs_auto.ycp +++ /dev/null @@ -1,111 +0,0 @@ -/** - * File: - * nfs_auto.ycp - * - * Package: - * Configuration of NFS client - * - * Summary: - * Client for autoinstallation - * - * Authors: - * Martin Vidner - * - * $Id$ - * - * This is a client for autoinstallation. It takes its arguments, - * goes through the configuration and return the setting. - * Does not do any changes to the configuration. - */ - -/** - * @param first a map of mail settings - * @return map edited settings or empty map if canceled - * @example map mm = $[ "FAIL_DELAY" : "77" ]; - * @example map ret = WFM::CallModule ("mail_auto", [ mm ]); - */ - -{ -textdomain "nfs"; - -y2milestone("----------------------------------------"); -y2milestone("Nfs auto started"); - -import "Nfs"; -import "Wizard"; -include "nfs/ui.ycp"; - -any ret = nil; -string func = ""; -map param = $[]; - -/* Check arguments */ -if(size(WFM::Args()) > 0 && is(WFM::Args(0), string)) { - func = (string) WFM::Args(0); - if(size(WFM::Args()) > 1 && is(WFM::Args(1), map)) - param = ( map ) WFM::Args(1); - if(size(WFM::Args()) > 1 && is(WFM::Args(1), list)) - y2warning("Old-style configuration detected (got list, expected map). section needs to be converted to match up-to-date schema"); -} -y2debug("func=%1", func); -y2debug("param=%1", param); - -/* Create a summary*/ -if(func == "Import") { - ret = (boolean) Nfs::Import(param); -} -/* Create a summary*/ -else if(func == "Summary") { - ret = (string) Nfs::Summary(); -} -/* Reset configuration */ -else if (func == "Reset") { - Nfs::Import($[]); - ret = $[]; -} -/* Change configuration (run AutoSequence) */ -else if (func == "Change") { - Wizard::CreateDialog (); - Wizard::SetDesktopIcon("nfs"); - ret = (symbol) FstabDialog (); - UI::CloseDialog (); -} -else if (func == "GetModified") { - ret = Nfs::GetModified(); -} -else if (func == "SetModified") { - Nfs::SetModified(); -} -/* Return actual state */ -else if (func == "Packages") { - ret = (map) Nfs::AutoPackages(); -} -/* Return actual state */ -else if (func == "Export") { - ret = (map) Nfs::Export(); -} -else if (func == "Read") { - ret = (boolean) Nfs::Read(); -} -/* Write givven settings */ -else if (func == "Write") { - import "Progress"; - boolean progress_orig = Progress::set (false); - ret = (boolean) Nfs::WriteOnly(); - Progress::set (progress_orig); -} -/* Unknown function */ -else { - y2error("Unknown function: %1", func); - ret = false; -} - -y2debug("ret=%1", ret); -y2milestone("Nfs auto finished"); -y2milestone("----------------------------------------"); - -return ret; - -/* EOF */ -} - diff --git a/src/include/nfs/routines.rb b/src/include/nfs/routines.rb new file mode 100644 index 0000000..694680d --- /dev/null +++ b/src/include/nfs/routines.rb @@ -0,0 +1,197 @@ +# encoding: utf-8 + +# File: +# routines.ycp +# +# Module: +# Configuration of nfs +# +# Summary: +# Network NFS routines +# +# Authors: +# Jan Holesovsky +# Dan Vesely +# +# $Id$ +# +# Network NFS routines +# +module Yast + module NfsRoutinesInclude + def initialize_nfs_routines(include_target) + textdomain "nfs" + + Yast.import "Package" + Yast.import "Report" + Yast.import "IP" + Yast.import "Hostname" + Yast.import "String" + end + + # @param [String] spec "server:/path/specification" + # @return `couple("server", "/path/specification") + def SpecToServPath(spec) + # split using ":/" (because of IPv6) + path_begin = Builtins.search(spec, ":/") + serv = "" + + # no :/ inside => : or [/] + if path_begin == nil + if spec == + Ops.add( + Builtins.filterchars(spec, Ops.add("-_.", String.CAlnum)), + ":" + ) + # matches [a-zA-Z0-1.-_] and ends with colon? => : + path_begin = Ops.subtract(Builtins.size(spec), 1) + end + end + + if path_begin != nil + serv = Builtins.substring(spec, 0, path_begin) + spec = Builtins.substring(spec, Ops.add(path_begin, 1)) + end + term(:couple, serv, spec) + end + + + # Creates a list of ui table items for nfs fstab entries + # @param [Array] fstab list of nfs fstab entries + # @return itemized table entries + # @example UI::ChangeWidget(`id(`fstable), `Items, FstabTableItems(nfs_entries)); + def FstabTableItems(fstab) + fstab = deep_copy(fstab) + count = 0 + Builtins.maplist(fstab) do |entry| + sp = SpecToServPath(Ops.get_string(entry, "spec", "")) + it = Item( + Id(count), + Ops.add(Ops.get_string(sp, 0, ""), " "), + Ops.add(Ops.get_string(sp, 1, ""), " "), + Ops.add(Ops.get_string(entry, "file", ""), " "), + Ops.get_string(entry, "vfstype", " "), + Ops.add(Ops.get_string(entry, "mntops", ""), " ") + ) + count = Ops.add(count, 1) + deep_copy(it) + end + end + + # Check for the validity of a hostname: nonempty, shorter than 50 chars, + # [-A-Za-z._]. If invalid, a message is displayed. + # @param [String] name a hostname + # @return whether valid + def CheckHostName(name) + Builtins.y2milestone("CheckHostName: hostname=%1", name) + + if Ops.greater_than(Builtins.size(name), 0) && + Ops.less_than(Builtins.size(name), 50) + return true if IP.Check4(name) + return true if IP.Check6(IP.UndecorateIPv6(name)) + return true if Hostname.CheckDomain(name) + end + + # error popup message + + Report.Error( + Builtins.sformat( + _( + "The hostname entered is invalid. It must be\n" + + "shorter than 50 characters and only use\n" + + "valid IPv4, IPv6 or domain name.\n" + + "Valid IPv4: %1\n" + + "Valid IPv6: %2\n" + + "Valid domain: %3" + ), + IP.Valid4, + IP.Valid6, + Hostname.ValidDomain + ) + ) + + false + end + + # Check if a mountpoint is in the fstab. If yes, display a message. + # @param [Array] fstab in .etc.fstab format (must contain the key "file") + # @param [String] mpoint mount point + # @return is it there? + def IsMpInFstab(fstab, mpoint) + fstab = deep_copy(fstab) + tmp = Builtins.filter(fstab) do |fse| + Ops.get_string(fse, "file", "") == mpoint + end + + if Builtins.size(tmp) == 0 + return false + else + # error popup message + Report.Error( + Builtins.sformat( + _("fstab already contains an entry\nwith mount point '%1'."), + mpoint + ) + ) + end + true + end + + # Check for the validity of a path/mountpoint: + # nonempty, fewer than 70 chars, starts with a slash. + # If invalid, a message is displayed. + # @param [String] name path + # @return whether valid + def CheckPath(name) + if Ops.greater_than(Builtins.size(name), 0) && + Ops.less_than(Builtins.size(name), 70) && + Builtins.substring(name, 0, 1) == "/" + return true + end + + # error popup message (spaces are now allowed) + Report.Error( + Builtins.sformat( + _( + "The path entered is invalid.\n" + + "It must be shorter than 70 characters\n" + + "and it must begin with a slash (/)." + ) + ) + ) + false + end + + + # Strips a superfluous slash off the end of a pathname. + # @param [String] p pathname + # @return stripped pathname + def StripExtraSlash(p) + if Builtins.regexpmatch(p, "^.+/$") + return Builtins.regexpsub(p, "^(.+)/$", "\\1") + else + return p + end + end + + # Formats hostname into form suitable for fstab. + # If given param is IPv6 then encloses it into square brackets. + def FormatHostnameForFstab(hostname) + Builtins.y2milestone("FormatHostnameForFstab: hostname=%1", hostname) + + if IP.Check6(IP.UndecorateIPv6(hostname)) + return Builtins.sformat( + Builtins.regexpmatch(hostname, "\\[.*\\]") ? "%1" : "[%1]", + hostname + ) + end + hostname + end + + # Check whether pormap is installed, ask user to install it if it is missing + # @return [Boolean] true if portmap is installed + def IsPortmapperInstalled(portmapper) + Package.Install(portmapper) + end + end +end diff --git a/src/include/nfs/routines.ycp b/src/include/nfs/routines.ycp deleted file mode 100644 index a24ef8a..0000000 --- a/src/include/nfs/routines.ycp +++ /dev/null @@ -1,189 +0,0 @@ -/** - * File: - * routines.ycp - * - * Module: - * Configuration of nfs - * - * Summary: - * Network NFS routines - * - * Authors: - * Jan Holesovsky - * Dan Vesely - * - * $Id$ - * - * Network NFS routines - * - */ - -{ - textdomain "nfs"; - - import "Package"; - import "Report"; - import "IP"; - import "Hostname"; - import "String"; - - /** - * @param spec "server:/path/specification" - * @return `couple("server", "/path/specification") - */ - define term SpecToServPath(string spec) ``{ - // split using ":/" (because of IPv6) - integer path_begin = search( spec, ":/"); - string serv = ""; - - // no :/ inside => : or [/] - if( path_begin == nil ) - { - if(spec == filterchars(spec, "-_." + String::CAlnum() ) + ":") - // matches [a-zA-Z0-1.-_] and ends with colon? => : - path_begin = size( spec) -1; - } - - if (path_begin != nil) { - serv = substring(spec, 0, path_begin); - spec = substring(spec, path_begin+1); - } - return `couple(serv, spec); - } - - - /** - * Creates a list of ui table items for nfs fstab entries - * @param fstab list of nfs fstab entries - * @return itemized table entries - * @example UI::ChangeWidget(`id(`fstable), `Items, FstabTableItems(nfs_entries)); - */ - define list FstabTableItems(list fstab) ``{ - integer count = 0; - return maplist(map entry, fstab, ``{ - term sp = SpecToServPath(entry["spec"]:""); - term it = `item(`id(count), - sp[0]:"" + " ", - sp[1]:"" + " ", - entry["file"]:"" + " ", - entry["vfstype"]:" ", - entry["mntops"]:"" + " "); - - count = count+1; - return it; - }); - } - - /** - * Check for the validity of a hostname: nonempty, shorter than 50 chars, - * [-A-Za-z._]. If invalid, a message is displayed. - * @param name a hostname - * @return whether valid - */ - define boolean CheckHostName(string name) ``{ - - y2milestone( "CheckHostName: hostname=%1", name); - - if (size(name) > 0 && - size(name) < 50) - { - if( IP::Check4( name)) - return true; - if( IP::Check6( IP::UndecorateIPv6( name))) - return true; - if( Hostname::CheckDomain( name)) - return true; - } - - // error popup message - - Report::Error ( sformat(_("The hostname entered is invalid. It must be -shorter than 50 characters and only use -valid IPv4, IPv6 or domain name. -Valid IPv4: %1 -Valid IPv6: %2 -Valid domain: %3"), IP::Valid4(), IP::Valid6(), Hostname::ValidDomain()) ); - - return false; - }; - - /** - * Check if a mountpoint is in the fstab. If yes, display a message. - * @param fstab in .etc.fstab format (must contain the key "file") - * @param mpoint mount point - * @return is it there? - */ - define boolean IsMpInFstab(list fstab, string mpoint) ``{ - list tmp = filter(map fse, fstab, ``{ - return (fse["file"]:"" == mpoint); - }); - - if (size(tmp) == 0) - return false; - else - // error popup message - Report::Error (sformat(_("fstab already contains an entry -with mount point '%1'."), mpoint)); - return true; - }; - - /** - * Check for the validity of a path/mountpoint: - * nonempty, fewer than 70 chars, starts with a slash. - * If invalid, a message is displayed. - * @param name path - * @return whether valid - */ - define boolean CheckPath(string name) ``{ - if (size(name) > 0 && - size(name) < 70 && - substring(name, 0, 1) == "/") - { - return true; - } - - // error popup message (spaces are now allowed) - Report::Error (sformat(_("The path entered is invalid. -It must be shorter than 70 characters -and it must begin with a slash (/)."))); - return false; - }; - - - /** - * Strips a superfluous slash off the end of a pathname. - * @param p pathname - * @return stripped pathname - */ - define string StripExtraSlash (string p) ``{ - if (regexpmatch (p, "^.+/$")) - { - return regexpsub (p, "^(.+)/$", "\\1"); - } - else - { - return p; - } - } - - /** - * Formats hostname into form suitable for fstab. - * If given param is IPv6 then encloses it into square brackets. - */ - define string FormatHostnameForFstab( string hostname) - { - y2milestone( "FormatHostnameForFstab: hostname=%1", hostname); - - if( IP::Check6( IP::UndecorateIPv6( hostname))) - return sformat( regexpmatch( hostname, "\\[.*\\]") ? "%1" : "[%1]", hostname); - return hostname; - } - - /** - * Check whether pormap is installed, ask user to install it if it is missing - * @return boolean true if portmap is installed - */ - define boolean IsPortmapperInstalled( string portmapper ) ``{ - return Package::Install( portmapper ); - } -} diff --git a/src/include/nfs/ui.rb b/src/include/nfs/ui.rb new file mode 100644 index 0000000..d49d50d --- /dev/null +++ b/src/include/nfs/ui.rb @@ -0,0 +1,738 @@ +# encoding: utf-8 + +# File: +# ui.ycp +# +# Module: +# Configuration of nfs +# +# Summary: +# Network NFS client dialogs +# +# Authors: +# Jan Holesovsky +# Dan Vesely +# Martin Vidner +# +# $Id$ +# +# Network NFS client dialogs +# +module Yast + module NfsUiInclude + def initialize_nfs_ui(include_target) + Yast.import "UI" + textdomain "nfs" + + Yast.import "CWMFirewallInterfaces" + Yast.import "Hostname" + Yast.import "FileUtils" + Yast.import "Label" + Yast.import "Nfs" + Yast.import "NfsOptions" + Yast.import "Popup" + Yast.import "SuSEFirewall" + Yast.import "Wizard" + Yast.include include_target, "nfs/routines.rb" + + # Caches names of nfs servers for GetFstabEntry + + @hosts = nil + + # List of already defined nfs mount points + @nfs_entries = deep_copy(Nfs.nfs_entries) + + # firewall widget using CWM + @fw_settings = { + "services" => ["service:nfs-client"], + "display_details" => true + } + @fw_cwm_widget = CWMFirewallInterfaces.CreateOpenFirewallWidget( + @fw_settings + ) + + @modify_line = {} + + # Help, part 1 of 3 + @help_text1 = _( + "

The table contains all directories \nexported from remote servers and mounted locally via NFS (NFS shares).

" + ) + + # Help, part 2 of 3 + _( + "

Each NFS share is identified by remote NFS server address and\n" + + "exported directory, local directory where the remote directory is mounted, \n" + + "NFS type (either plain nfs or nfsv4) and mount options. For further information \n" + + "about mounting NFS and mount options, refer to man nfs.

" + ) + + # Help, part 3 of 3 + _( + "

To mount a new NFS share, click Add. To change the configuration of\n" + + "a currently mounted share, click Edit. Remove and unmount a selected\n" + + "share with Delete.

\n" + ) + + + @help_text2 = Ops.add( + _( + "

If you need to access NFSv4 shares (NFSv4 is a newer version of the NFS\n" + + "protocol), check the Enable NFSv4 option. In that case, you might need\n" + + "to supply specific a NFSv4 Domain Name required for the correct setting\n" + + "of file/directory access rights.

\n" + ), + Ops.get_string(@fw_cwm_widget, "help", "") + ) + end + + # Read settings dialog + # @return `abort if aborted and `next otherwise + def ReadDialog + ret = nil + ret = Nfs.Read + ret ? :next : :abort + end + + # Write settings dialog + # @return `abort if aborted and `next otherwise + def WriteDialog + ret = Nfs.Write + ret ? :next : :abort + end + + # Let the user choose one of a list of items + # @param [String] title selectionbox title + # @param [Array] items a list of items + # @return one item or nil + def ChooseItem(title, items) + items = deep_copy(items) + item = nil + + UI.OpenDialog( + VBox( + HSpacing(40), + HBox(SelectionBox(Id(:items), title, items), VSpacing(10)), + ButtonBox( + PushButton(Id(:ok), Opt(:default, :key_F10), Label.OKButton), + PushButton(Id(:cancel), Opt(:key_F9), Label.CancelButton) + ) + ) + ) + UI.SetFocus(Id(:items)) + ret = nil + begin + ret = UI.UserInput + end while ret != :cancel && ret != :ok + + if ret == :ok + item = Convert.to_string(UI.QueryWidget(Id(:items), :CurrentItem)) + end + UI.CloseDialog + + item + end + + # Find out whether this nfs host really exists + # @param [String] hname hostname + # @return true if it exists, false otherwise + def HostnameExists(hname) + prog_name = "/usr/bin/host" + ret = false + + if FileUtils.Exists(prog_name) + out = Convert.to_map( + SCR.Execute( + path(".target.bash_output"), + Builtins.sformat("%1 %2", prog_name, hname) + ) + ) + + ret = Ops.get_integer(out, "exit", -1) == 0 + Builtins.y2debug("DNS lookup of %1 returned %2", hname, ret) + else + Builtins.y2warning( + "Cannot DNS lookup %1, will not propose default hostname", + hname + ) + end + + ret + end + + # Return convenient hostname (FaTE #302863) to be proposed + # i.e. nfs + current domain (nfs. + suse.cz) + # @return string proposed hostname + def ProposeHostname + ret = "" + cur_domain = Hostname.CurrentDomain + + ret = Ops.add("nfs.", cur_domain) if cur_domain != nil || cur_domain != "" + ret + end + + # Give me one name from the list of hosts + # @param [Array] hosts a list of hostnames + # @return a hostname + def ChooseHostName(hosts) + hosts = deep_copy(hosts) + Wizard.SetScreenShotName("nfs-client-1aa-hosts") + # selection box label + # changed from "Remote hosts" because now it shows + # NFS servers only + ret = ChooseItem(_("&NFS Servers"), hosts) + Wizard.RestoreScreenShotName + ret + end + + # Give me one name from the list of exports + # @param [Array] exports a list of exports + # @return an export + def ChooseExport(exports) + exports = deep_copy(exports) + Wizard.SetScreenShotName("nfs-client-1ab-exports") + # selection box label + ret = ChooseItem(_("&Exported Directories"), exports) + Wizard.RestoreScreenShotName + ret + end + + # Nicely put a `TextEntry and its helper `PushButton together + # @param [Yast::Term] text textentry widget + # @param [Yast::Term] button pushbutton widget + # @return a HBox + def TextAndButton(text, button) + text = deep_copy(text) + button = deep_copy(button) + HBox(Bottom(text), HSpacing(0.5), Bottom(button)) + end + + # Ask user for an entry. + # @param [Hash{String => Object}] fstab_ent $["spec": "file": "mntops":] or nil + # @param [Array] existing list of fstab entries for duplicate mount-point checking + # @return a nfs_entry or nil + def GetFstabEntry(fstab_ent, existing) + fstab_ent = deep_copy(fstab_ent) + existing = deep_copy(existing) + Wizard.SetScreenShotName("nfs-client-1a-edit") + + server = "" + pth = "" + mount = "" + nfs4 = false + nfs41 = false + options = "defaults" + servers = [] + old = "" + + if fstab_ent != nil + couple = SpecToServPath(Ops.get_string(fstab_ent, "spec", "")) + server = Ops.get_string(couple, 0, "") + pth = Ops.get_string(couple, 1, "") + mount = Ops.get_string(fstab_ent, "file", "") + nfs4 = Ops.get_string(fstab_ent, "vfstype", "") == "nfs4" + options = Ops.get_string(fstab_ent, "mntops", "") + nfs41 = nfs4 && NfsOptions.get_nfs41(options) + servers = [server] + old = Ops.get_string(fstab_ent, "spec", "") + else + proposed_server = ProposeHostname() + servers = [proposed_server] if HostnameExists(proposed_server) + end + + # append already defined servers - bug #547983 + Builtins.foreach(@nfs_entries) do |nfs_entry| + couple = SpecToServPath(Ops.get_string(nfs_entry, "spec", "")) + known_server = Ops.get_string(couple, 0, "") + if !Builtins.contains(servers, known_server) + servers = Builtins.add(servers, known_server) + end + end + + servers = Builtins.sort(servers) + # + + UI.OpenDialog( + Opt(:decorated), + HBox( + HSpacing(1), + VBox( + VSpacing(0.2), + HBox( + TextAndButton( + ComboBox( + Id(:serverent), + Opt(:editable), + # text entry label + _("&NFS Server Hostname"), + servers + ), + # pushbutton label + # choose a host from a list + # appears in help text too + PushButton(Id(:choose), _("Choo&se")) + ), + HSpacing(0.5), + TextAndButton( + InputField( + Id(:pathent), + Opt(:hstretch), + # textentry label + _("&Remote Directory"), + pth + ), + # pushbutton label, + # select from a list of remote filesystems + # make it short + # appears in help text too + PushButton(Id(:pathent_list), _("&Select")) + ) + ), + Left( + HBox( + CheckBox(Id(:nfs4), _("NFS&v4 Share"), nfs4), + HSpacing(2), + # parallel NFS, protocol version 4.1 + CheckBox(Id(:nfs41), _("pNFS (v4.1)"), nfs41) + ) + ), + Left( + TextAndButton( + InputField( + Id(:mountent), + Opt(:hstretch), + # textentry label + _("&Mount Point (local)"), + mount + ), + # button label + # browse directories to select a mount point + # appears in help text too + PushButton(Id(:browse), _("&Browse")) + ) + ), + # textentry label + VSpacing(0.2), + InputField(Id(:optionsent), Opt(:hstretch), _("O&ptions"), options), + VSpacing(0.2), + ButtonBox( + PushButton(Id(:ok), Opt(:default, :key_F10), Label.OKButton), + PushButton(Id(:cancel), Opt(:key_F9), Label.CancelButton), + PushButton(Id(:help), Opt(:key_F1), Label.HelpButton) + ), + VSpacing(0.2) + ), + HSpacing(1) + ) + ) + UI.ChangeWidget(Id(:serverent), :Value, server) + UI.SetFocus(Id(:serverent)) + + ret = nil + begin + ret = UI.UserInput + + if ret == :choose + if @hosts == nil + # label message + UI.OpenDialog(Label(_("Scanning for hosts on this LAN..."))) + @hosts = Nfs.ProbeServers + UI.CloseDialog + end + if @hosts == [] || @hosts == nil + #Translators: 1st part of error message + error_msg = _("No NFS server has been found on your network.") + + if SuSEFirewall.GetStartService + #Translators: 2nd part of error message (1st one is 'No nfs servers have been found ...) + error_msg = Ops.add( + error_msg, + _( + "\n" + + "This could be caused by a running SuSEfirewall2,\n" + + "which probably blocks the network scanning." + ) + ) + end + Report.Error(error_msg) + else + host = ChooseHostName(@hosts) + UI.ChangeWidget(Id(:serverent), :Value, host) if host != nil + end + elsif ret == :pathent_list + server2 = Convert.to_string(UI.QueryWidget(Id(:serverent), :Value)) + v4 = Convert.to_boolean(UI.QueryWidget(Id(:nfs4), :Value)) + + if !CheckHostName(server2) + UI.SetFocus(Id(:serverent)) + next + end + + UI.OpenDialog( + Label( + # Popup dialog, %1 is a host name + Builtins.sformat( + _("Getting directory list for \"%1\"..."), + server2 + ) + ) + ) + dirs = Nfs.ProbeExports(server2, v4) + UI.CloseDialog + + dir = ChooseExport(dirs) + UI.ChangeWidget(Id(:pathent), :Value, dir) if dir != nil + elsif ret == :browse + dir = Convert.to_string(UI.QueryWidget(Id(:mountent), :Value)) + dir = "/" if dir == nil || Builtins.size(dir) == 0 + + # heading for a directory selection dialog + dir = UI.AskForExistingDirectory(dir, _("Select the Mount Point")) + + if dir != nil && Ops.greater_than(Builtins.size(dir), 0) + UI.ChangeWidget(Id(:mountent), :Value, dir) + end + elsif ret == :ok + server = FormatHostnameForFstab( + Convert.to_string(UI.QueryWidget(Id(:serverent), :Value)) + ) + pth = StripExtraSlash( + Convert.to_string(UI.QueryWidget(Id(:pathent), :Value)) + ) + mount = StripExtraSlash( + Convert.to_string(UI.QueryWidget(Id(:mountent), :Value)) + ) + nfs4 = Convert.to_boolean(UI.QueryWidget(Id(:nfs4), :Value)) + nfs41 = Convert.to_boolean(UI.QueryWidget(Id(:nfs41), :Value)) + options = Builtins.deletechars( + Convert.to_string(UI.QueryWidget(Id(:optionsent), :Value)), + " " + ) + options = NfsOptions.set_nfs41(options, nfs41) + + ret = nil + options_error = NfsOptions.validate(options) + if !CheckHostName(server) + UI.SetFocus(Id(:serverent)) + elsif !CheckPath(pth) + UI.SetFocus(Id(:pathent)) + elsif !CheckPath(mount) || IsMpInFstab(existing, mount) + UI.SetFocus(Id(:mountent)) + elsif Ops.greater_than(Builtins.size(options_error), 0) + Popup.Error(options_error) + UI.SetFocus(Id(:optionsent)) + else + fstab_ent = { + "spec" => Ops.add(Ops.add(server, ":"), pth), + "file" => mount, + "vfstype" => nfs4 ? "nfs4" : "nfs", + "mntops" => options + } + if old != Ops.add(Ops.add(server, ":"), pth) + fstab_ent = Builtins.add(fstab_ent, "old", old) + end + ret = :ok + end + elsif ret == :help + #help text 1/4 + # change: locally defined -> servers on LAN + helptext = _( + "

Enter the NFS Server Hostname. With\n" + + "Choose, browse through a list of\n" + + "NFS servers on the local network.

\n" + ) + # help text 2/4 + # added "Select" button + helptext = Ops.add( + helptext, + _( + "

In Remote File System,\n" + + "enter the path to the directory on the NFS server. Use\n" + + "Select to select one from those exported by the server.\n" + + "

" + ) + ) + # help text 3/4 + helptext = Ops.add( + helptext, + _( + "

\t\t\n" + + "For Mount Point, enter the path in the local file system where the directory should be mounted. With\n" + + "Browse, select your mount point\n" + + "interactively.

" + ) + ) + # help text 4/4 + helptext = Ops.add( + helptext, + _( + "

For a list of Options,\nread the man page mount(8).

" + ) + ) + # popup heading + Popup.LongText(_("Help"), RichText(helptext), 50, 18) + end + end while ret != :ok && ret != :cancel + + UI.CloseDialog + Wizard.RestoreScreenShotName + + return deep_copy(fstab_ent) if ret == :ok + nil + end + + def EnableDisableButtons + UI.ChangeWidget(Id(:editbut), :Enabled, @nfs_entries != []) + UI.ChangeWidget(Id(:delbut), :Enabled, @nfs_entries != []) + + nil + end + + def FstabTab + fstab_content = VBox( + Table( + Id(:fstable), + Opt(:notify, :immediate), + Header( + # table header + _("Server") + " ", + _("Remote Directory") + " ", + # table header + _("Mount Point") + " ", + # table header + _("NFS Type"), + # table header + _("Options") + " " + ), + FstabTableItems(@nfs_entries) + ), + HBox( + PushButton(Id(:newbut), Opt(:key_F3), Label.AddButton), + PushButton(Id(:editbut), Opt(:key_F4), Label.EditButton), + PushButton(Id(:delbut), Opt(:key_F5), Label.DeleteButton), + # #211570 + HStretch() + ) + ) + + deep_copy(fstab_content) + end + + def SettingsTab + settings_content = VBox( + #`VSpacing (1), + HBox( + Left(CheckBox(Id(:enable_nfs4), Opt(:notify), _("Enable NFSv4"))), + Left(InputField(Id(:nfs4_domain), _("NFSv4 Domain Name"))), + HStretch() + ), + VSpacing(1), + Left( + CheckBox(Id(:enable_nfs_gss), Opt(:notify), _("Enable &GSS Security")) + ), + VSpacing(1), + Ops.get_term(@fw_cwm_widget, "custom_widget", Empty()), + VStretch() + ) + + deep_copy(settings_content) + end + + def MainDialogLayout + contents = VBox( + DumbTab( + [ + Item(Id(:overview), _("&NFS Shares")), + Item(Id(:settings), _("NFS &Settings")) + ], + ReplacePoint(Id(:rp), FstabTab()) + ) + ) + + deep_copy(contents) + end + + def InitFstabEntries + UI.ChangeWidget(Id(:fstable), :Items, FstabTableItems(@nfs_entries)) + EnableDisableButtons() + + nil + end + + def InitSettings + CWMFirewallInterfaces.OpenFirewallInit(@fw_cwm_widget, "") + UI.ChangeWidget(Id(:enable_nfs4), :Value, Nfs.nfs4_enabled != false) + UI.ChangeWidget(Id(:nfs4_domain), :Enabled, Nfs.nfs4_enabled != false) + UI.ChangeWidget(Id(:nfs4_domain), :Value, Nfs.idmapd_domain) + UI.ChangeWidget(Id(:enable_nfs_gss), :Value, Nfs.nfs_gss_enabled != false) + + nil + end + + def SaveFstabEntries + Nfs.nfs_entries = deep_copy(@nfs_entries) + + nil + end + + def SaveSettings(event) + event = deep_copy(event) + CWMFirewallInterfaces.OpenFirewallStore(@fw_cwm_widget, "", event) + Nfs.nfs4_enabled = Convert.to_boolean( + UI.QueryWidget(Id(:enable_nfs4), :Value) + ) + Nfs.nfs_gss_enabled = Convert.to_boolean( + UI.QueryWidget(Id(:enable_nfs_gss), :Value) + ) + Nfs.idmapd_domain = Convert.to_string( + UI.QueryWidget(Id(:nfs4_domain), :Value) + ) + + nil + end + + def HandleEvent(widget) + widget = deep_copy(widget) + entryno = -1 + # handle the events, enable/disable the button, show the popup if button clicked + if UI.WidgetExists(Id("_cwm_firewall_details")) && + UI.WidgetExists(Id("_cwm_open_firewall")) + CWMFirewallInterfaces.OpenFirewallHandle( + @fw_cwm_widget, + "", + { "ID" => widget } + ) + end + if UI.WidgetExists(Id(:fstable)) + entryno = Convert.to_integer(UI.QueryWidget(Id(:fstable), :CurrentItem)) + end + + if widget == :newbut + entry = GetFstabEntry( + nil, + Convert.convert( + Builtins.union(Nfs.non_nfs_entries, @nfs_entries), + :from => "list", + :to => "list " + ) + ) + + if entry != nil + @nfs_entries = Builtins.add(@nfs_entries, entry) + @modify_line = deep_copy(entry) + EnableDisableButtons() + + Nfs.SetModified + end + + UI.ChangeWidget(Id(:fstable), :Items, FstabTableItems(@nfs_entries)) + elsif widget == :editbut + count = 0 + entry = GetFstabEntry( + Ops.get(@nfs_entries, entryno, {}), + Convert.convert( + Builtins.union( + Nfs.non_nfs_entries, + Builtins.remove(@nfs_entries, entryno) + ), + :from => "list", + :to => "list " + ) # Default values + ) + if entry != nil + count2 = 0 + @nfs_entries = Builtins.maplist(@nfs_entries) do |ent| + count2 = Ops.add(count2, 1) + next deep_copy(ent) if Ops.subtract(count2, 1) != entryno + deep_copy(entry) + end + + @modify_line = deep_copy(entry) + UI.ChangeWidget(Id(:fstable), :Items, FstabTableItems(@nfs_entries)) + Nfs.SetModified + end + elsif widget == :delbut && + Ops.greater_than(Builtins.size(@nfs_entries), 0) + share = Ops.get(@nfs_entries, entryno, {}) + if Popup.YesNo( + Builtins.sformat( + _("Really delete %1?"), + Ops.get_string(share, "spec", "") + ) + ) + @modify_line = deep_copy(share) + @nfs_entries = Builtins.remove(@nfs_entries, entryno) + UI.ChangeWidget(Id(:fstable), :Items, FstabTableItems(@nfs_entries)) + EnableDisableButtons() + + Nfs.SetModified + end + elsif widget == :enable_nfs4 + enabled = Convert.to_boolean(UI.QueryWidget(Id(:enable_nfs4), :Value)) + UI.ChangeWidget(Id(:nfs4_domain), :Enabled, enabled) + Nfs.SetModified + elsif widget == :settings + SaveFstabEntries() + UI.ReplaceWidget(Id(:rp), SettingsTab()) + InitSettings() + Wizard.SetHelpText(@help_text2) + elsif widget == :overview + SaveSettings({ "ID" => widget }) + UI.ReplaceWidget(Id(:rp), FstabTab()) + InitFstabEntries() + Wizard.SetHelpText(@help_text1) + end + + nil + end + + # NFS client dialog itselfs + # @return `back, `abort or `next + def FstabDialog + Wizard.SetScreenShotName("nfs-client-1-fstab") + + @nfs_entries = deep_copy(Nfs.nfs_entries) + + # dialog heading + Wizard.SetContents( + _("NFS Client Configuration"), + MainDialogLayout(), + @help_text1, + false, + true + ) + #Wizard::HideBackButton(); + #Wizard::SetAbortButton(`abort, Label::CancelButton()); + + InitFstabEntries() + + # Kludge, because a `Table still does not have a shortcut. + # Simple to solve here: there's only the table and buttons, + # so it is OK to always set focus to the table + UI.SetFocus(Id(:fstable)) + + event = nil + ret = nil + entryno = -1 + begin + event = UI.WaitForEvent + ret = Ops.get(event, "ID") + if ret == :ok + ret = :next + elsif ret == :cancel + ret = :abort + elsif ret == :abort && Nfs.GetModified && !Popup.ReallyAbort(true) + ret = :again + else + HandleEvent(ret) + end + end while ret != :back && ret != :next && ret != :abort + + if ret == :next + # grab current settings, store them to SuSEFirewall:: + SaveFstabEntries() if UI.WidgetExists(Id(:fstable)) + SaveSettings(event) if UI.WidgetExists(Id(:enable_nfs4)) + end + + Wizard.RestoreScreenShotName + Convert.to_symbol(ret) + end + end +end diff --git a/src/include/nfs/ui.ycp b/src/include/nfs/ui.ycp deleted file mode 100644 index 3b55cea..0000000 --- a/src/include/nfs/ui.ycp +++ /dev/null @@ -1,731 +0,0 @@ -/** - * File: - * ui.ycp - * - * Module: - * Configuration of nfs - * - * Summary: - * Network NFS client dialogs - * - * Authors: - * Jan Holesovsky - * Dan Vesely - * Martin Vidner - * - * $Id$ - * - * Network NFS client dialogs - * - */ - -{ - textdomain "nfs"; - - import "CWMFirewallInterfaces"; - import "Hostname"; - import "FileUtils"; - import "Label"; - import "Nfs"; - import "NfsOptions"; - import "Popup"; - import "SuSEFirewall"; - import "Wizard"; - include "nfs/routines.ycp"; - - /** - * Read settings dialog - * @return `abort if aborted and `next otherwise - */ - symbol ReadDialog() { - boolean ret = nil; - ret = Nfs::Read (); - return ret ? `next : `abort; - } - - /** - * Write settings dialog - * @return `abort if aborted and `next otherwise - */ - symbol WriteDialog() { - boolean ret = Nfs::Write (); - return ret ? `next : `abort; - } - - /** - * Caches names of nfs servers for GetFstabEntry - */ - - list hosts = nil; - - /** - * List of already defined nfs mount points - */ - list< map > nfs_entries = Nfs::nfs_entries; - - /** - * Let the user choose one of a list of items - * @param title selectionbox title - * @param items a list of items - * @return one item or nil - */ - define string ChooseItem (string title, list items) ``{ - string item = nil; - - UI::OpenDialog ( - `VBox ( - `HSpacing (40), - `HBox ( - `SelectionBox (`id (`items), title, items), - `VSpacing(10) - ), - `ButtonBox ( - `PushButton (`id (`ok), `opt (`default, `key_F10), - Label::OKButton ()), - `PushButton (`id (`cancel), `opt (`key_F9), - Label::CancelButton()) - ) - )); - UI::SetFocus (`id (`items)); - any ret = nil; - do - { - ret = UI::UserInput(); - } - while (ret != `cancel && ret != `ok); - - if (ret == `ok) - { - item = (string) UI::QueryWidget (`id (`items), `CurrentItem); - } - UI::CloseDialog(); - - return item; - } - - /** - * Find out whether this nfs host really exists - * @param hname hostname - * @return true if it exists, false otherwise - */ - define boolean HostnameExists( string hname ){ - string prog_name = "/usr/bin/host"; - boolean ret = false; - - if (FileUtils::Exists( prog_name )) - { - map out = (map) SCR::Execute(.target.bash_output, - sformat("%1 %2",prog_name, hname )); - - ret = (out["exit"]: -1 == 0); - y2debug("DNS lookup of %1 returned %2", hname, ret ); - } - else - { - y2warning("Cannot DNS lookup %1, will not propose default hostname", hname); - } - - return ret; - } - - /* Return convenient hostname (FaTE #302863) to be proposed - * i.e. nfs + current domain (nfs. + suse.cz) - * @return string proposed hostname - */ - define string ProposeHostname() { - string ret = ""; - string cur_domain = Hostname::CurrentDomain(); - - if (cur_domain != nil || cur_domain != "") - { - ret = "nfs." + cur_domain; - } - return ret; - } - - /** - * Give me one name from the list of hosts - * @param hosts a list of hostnames - * @return a hostname - */ - define string ChooseHostName(list hosts) ``{ - Wizard::SetScreenShotName ("nfs-client-1aa-hosts"); - // selection box label - // changed from "Remote hosts" because now it shows - // NFS servers only - string ret = ChooseItem (_("&NFS Servers"), hosts); - Wizard::RestoreScreenShotName (); - return ret; - } - - /** - * Give me one name from the list of exports - * @param exports a list of exports - * @return an export - */ - define string ChooseExport (list exports) ``{ - Wizard::SetScreenShotName ("nfs-client-1ab-exports"); - // selection box label - string ret = ChooseItem (_("&Exported Directories"), exports); - Wizard::RestoreScreenShotName (); - return ret; - } - - /** - * Nicely put a `TextEntry and its helper `PushButton together - * @param text textentry widget - * @param button pushbutton widget - * @return a HBox - */ - define term TextAndButton (term text, term button) ``{ - return `HBox ( - `Bottom (text), - `HSpacing(0.5), - `Bottom (button) - ); - } - - /** - * Ask user for an entry. - * @param fstab_ent $["spec": "file": "mntops":] or nil - * @param existing list of fstab entries for duplicate mount-point checking - * @return a nfs_entry or nil - */ - define map GetFstabEntry(map fstab_ent, list existing) ``{ - Wizard::SetScreenShotName ("nfs-client-1a-edit"); - - string server = ""; - string pth = ""; - string mount = ""; - boolean nfs4 = false; - boolean nfs41 = false; - string options = "defaults"; - list servers = [ ]; - string old = ""; - - if (fstab_ent != nil) - { - term couple = SpecToServPath(fstab_ent["spec"]:""); - server = couple[0]:""; - pth = couple[1]:""; - mount = fstab_ent["file"]:""; - nfs4 = fstab_ent["vfstype"]:"" == "nfs4"; - options = fstab_ent["mntops"]:""; - nfs41 = nfs4 && NfsOptions::get_nfs41 (options); - servers = [ server ]; - old = fstab_ent["spec"]:""; - } - else - { - string proposed_server = ProposeHostname(); - if ( HostnameExists( proposed_server ) ) - servers = [ proposed_server ]; - } - - // append already defined servers - bug #547983 - foreach( map nfs_entry, nfs_entries, - { - term couple = SpecToServPath( nfs_entry[ "spec"]:""); - string known_server = couple[0]:""; - - if( !contains( servers, known_server)) - servers = add( servers, known_server); - }); - - servers = sort( servers); - // - - UI::OpenDialog( - `opt(`decorated), - `HBox( - `HSpacing(1), - `VBox( - `VSpacing(0.2), - `HBox( - TextAndButton ( - `ComboBox( - `id(`serverent),`opt(`editable), - // text entry label - _("&NFS Server Hostname"), servers ), - // pushbutton label - // choose a host from a list - // appears in help text too - `PushButton (`id (`choose), _("Choo&se")) - ), - `HSpacing(0.5), - TextAndButton ( - `InputField( `id(`pathent), - `opt(`hstretch), - // textentry label - _("&Remote Directory"), pth), - // pushbutton label, - // select from a list of remote filesystems - // make it short - // appears in help text too - `PushButton (`id (`pathent_list), _("&Select")) - ) - ), - `Left( - `HBox( - `CheckBox(`id(`nfs4), _("NFS&v4 Share"), nfs4), - `HSpacing(2), - // parallel NFS, protocol version 4.1 - `CheckBox(`id(`nfs41), _("pNFS (v4.1)"), nfs41) - ) - ), - `Left( - TextAndButton ( - `InputField(`id(`mountent), - `opt(`hstretch), - // textentry label - _("&Mount Point (local)"), mount), - // button label - // browse directories to select a mount point - // appears in help text too - `PushButton(`id(`browse), _("&Browse")) - ) - ), - // textentry label - `VSpacing(0.2), - `InputField(`id(`optionsent), `opt( `hstretch), _("O&ptions"), options), - `VSpacing(0.2), - `ButtonBox( - `PushButton(`id(`ok), `opt(`default, `key_F10), Label::OKButton()), - `PushButton(`id(`cancel), `opt (`key_F9), Label::CancelButton()), - `PushButton(`id(`help), `opt (`key_F1), Label::HelpButton())), - `VSpacing(0.2)), - `HSpacing(1) - )); - UI::ChangeWidget(`id(`serverent), `Value, server); - UI::SetFocus (`id (`serverent)); - - any ret = nil; - do - { - ret = UI::UserInput(); - - if (ret == `choose) - { - if (hosts == nil) - { - // label message - UI::OpenDialog(`Label(_("Scanning for hosts on this LAN..."))); - hosts = Nfs::ProbeServers(); - UI::CloseDialog(); - } - if( hosts == [] || hosts == nil ) - { - //Translators: 1st part of error message - string error_msg = _("No NFS server has been found on your network."); - - if ( SuSEFirewall::GetStartService() ) - { - //Translators: 2nd part of error message (1st one is 'No nfs servers have been found ...) - error_msg = error_msg + _("\nThis could be caused by a running SuSEfirewall2, -which probably blocks the network scanning."); - } - Report::Error(error_msg); - } - else - { - string host = ChooseHostName(hosts); - if (host != nil) - { - UI::ChangeWidget(`id(`serverent), `Value, host); - } - } - } - else if (ret == `pathent_list) - { - string server = (string) UI::QueryWidget(`id(`serverent), `Value); - boolean v4 = (boolean) UI::QueryWidget(`id(`nfs4), `Value); - - if (!CheckHostName (server)) - { - UI::SetFocus (`id (`serverent)); - continue; - } - - UI::OpenDialog ( - `Label ( - // Popup dialog, %1 is a host name - sformat (_("Getting directory list for \"%1\"..."), - server) - )); - list dirs = Nfs::ProbeExports (server, v4); - UI::CloseDialog (); - - string dir = ChooseExport (dirs); - if (dir != nil) - { - UI::ChangeWidget (`id (`pathent), `Value, dir); - } - } - else if (ret == `browse) - { - string dir = (string) UI::QueryWidget(`id (`mountent), `Value); - if (dir == nil || size (dir) == 0) - { - dir = "/"; - } - - // heading for a directory selection dialog - dir = UI::AskForExistingDirectory(dir, _("Select the Mount Point")); - - if (dir != nil && size(dir) > 0) - { - UI::ChangeWidget (`id (`mountent), `Value, dir); - } - } - else if (ret == `ok) - { - server = FormatHostnameForFstab( (string) UI::QueryWidget(`id(`serverent), `Value)); - pth = StripExtraSlash ((string) UI::QueryWidget(`id(`pathent), `Value)); - mount = StripExtraSlash ((string) UI::QueryWidget(`id(`mountent), `Value)); - nfs4 = (boolean) UI::QueryWidget(`id(`nfs4), `Value); - nfs41 = (boolean) UI::QueryWidget(`id(`nfs41), `Value); - options = deletechars ((string) UI::QueryWidget(`id(`optionsent), `Value), " "); - options = NfsOptions::set_nfs41(options, nfs41); - - ret = nil; - string options_error = NfsOptions::validate (options); - if (!CheckHostName (server)) - { - UI::SetFocus (`id (`serverent)); - } - else if (! CheckPath (pth)) - { - UI::SetFocus (`id (`pathent)); - } - else if (! CheckPath (mount) || IsMpInFstab (existing, mount)) - { - UI::SetFocus (`id (`mountent)); - } - else if (size (options_error) > 0) - { - Popup::Error(options_error); - UI::SetFocus (`id (`optionsent)); - } - else - { - fstab_ent = $[ - "spec" : server+":"+pth, - "file" : mount, - "vfstype" : nfs4 ? "nfs4" : "nfs", - "mntops" : options, - ]; - if (old != (server+":"+pth)) - fstab_ent = add(fstab_ent, "old", old); - ret = `ok; - } - } - else if (ret == `help) - { - //help text 1/4 - // change: locally defined -> servers on LAN - string helptext = _("

Enter the NFS Server Hostname. With -Choose, browse through a list of -NFS servers on the local network.

-"); - // help text 2/4 - // added "Select" button - helptext = helptext + _("

In Remote File System, -enter the path to the directory on the NFS server. Use -Select to select one from those exported by the server. -

"); - // help text 3/4 - helptext = helptext + _("

-For Mount Point, enter the path in the local file system where the directory should be mounted. With -Browse, select your mount point -interactively.

"); - // help text 4/4 - helptext = helptext + _("

For a list of Options, -read the man page mount(8).

"); - // popup heading - Popup::LongText (_("Help"), `RichText (helptext), 50, 18); - } - } - while (ret != `ok && ret != `cancel); - - UI::CloseDialog(); - Wizard::RestoreScreenShotName (); - - if (ret == `ok) - return fstab_ent; - return nil; - } - - // firewall widget using CWM - map fw_settings = $[ - "services": [ "service:nfs-client" ], - "display_details": true, - ]; - map fw_cwm_widget = CWMFirewallInterfaces::CreateOpenFirewallWidget (fw_settings); - - map modify_line = $[]; - - // Help, part 1 of 3 - string help_text1 = _("

The table contains all directories -exported from remote servers and mounted locally via NFS (NFS shares).

") + - - // Help, part 2 of 3 - _("

Each NFS share is identified by remote NFS server address and -exported directory, local directory where the remote directory is mounted, -NFS type (either plain nfs or nfsv4) and mount options. For further information -about mounting NFS and mount options, refer to man nfs.

") + - - // Help, part 3 of 3 -_("

To mount a new NFS share, click Add. To change the configuration of -a currently mounted share, click Edit. Remove and unmount a selected -share with Delete.

-"); - - - string help_text2 = _("

If you need to access NFSv4 shares (NFSv4 is a newer version of the NFS -protocol), check the Enable NFSv4 option. In that case, you might need -to supply specific a NFSv4 Domain Name required for the correct setting -of file/directory access rights.

-") + fw_cwm_widget["help"]:""; - - void EnableDisableButtons() - { - UI::ChangeWidget(`id(`editbut), `Enabled, ( nfs_entries != [] ) ); - UI::ChangeWidget(`id(`delbut), `Enabled, ( nfs_entries != [] ) ); - } - - term FstabTab() - { - term fstab_content = - `VBox( - `Table(`id(`fstable), `opt(`notify, `immediate), - `header( - // table header - _("Server")+" ", - _("Remote Directory")+" ", - // table header - _("Mount Point")+" ", - // table header - _("NFS Type"), - // table header - _("Options")+" "), - FstabTableItems(nfs_entries)), - `HBox(`PushButton(`id(`newbut), `opt (`key_F3), - Label::AddButton ()), - `PushButton(`id(`editbut), `opt (`key_F4), - Label::EditButton ()), - `PushButton(`id(`delbut), `opt (`key_F5), - Label::DeleteButton ()), - // #211570 - `HStretch ()) - ); - - return fstab_content; - - } - - term SettingsTab() - { - term settings_content = - `VBox( - //`VSpacing (1), - `HBox( - `Left(`CheckBox(`id(`enable_nfs4), `opt(`notify), _("Enable NFSv4"))), - `Left(`InputField(`id(`nfs4_domain), _("NFSv4 Domain Name"))), - `HStretch() - ), - `VSpacing (1), - `Left(`CheckBox(`id(`enable_nfs_gss), `opt( `notify), _("Enable &GSS Security"))), - `VSpacing (1), - fw_cwm_widget["custom_widget"]:`Empty (), - `VStretch() - ); - - return settings_content; - } - - term MainDialogLayout() - { - term contents = - `VBox( - `DumbTab( - [ `item(`id(`overview),_("&NFS Shares")), - `item(`id(`settings), _("NFS &Settings")) ], - `ReplacePoint(`id(`rp), FstabTab()) - ) - ); - - return contents; - } - - void InitFstabEntries( ) - { - UI::ChangeWidget (`id(`fstable), `Items, FstabTableItems (nfs_entries)); - EnableDisableButtons(); - - } - - void InitSettings( ) - { - CWMFirewallInterfaces::OpenFirewallInit (fw_cwm_widget, ""); - UI::ChangeWidget(`id(`enable_nfs4), `Value, Nfs::nfs4_enabled != false); - UI::ChangeWidget( `id(`nfs4_domain), `Enabled, Nfs::nfs4_enabled != false); - UI::ChangeWidget(`id(`nfs4_domain), `Value, Nfs::idmapd_domain); - UI::ChangeWidget(`id(`enable_nfs_gss), `Value, Nfs::nfs_gss_enabled != false); - } - - void SaveFstabEntries( ) - { - Nfs::nfs_entries = nfs_entries; - } - - void SaveSettings( map event ) - { - CWMFirewallInterfaces::OpenFirewallStore (fw_cwm_widget, "", event); - Nfs::nfs4_enabled = (boolean) UI::QueryWidget(`id(`enable_nfs4),`Value); - Nfs::nfs_gss_enabled = (boolean) UI::QueryWidget(`id(`enable_nfs_gss),`Value); - Nfs::idmapd_domain = (string) UI::QueryWidget(`id(`nfs4_domain),`Value); - } - - void HandleEvent( any widget ) - { - integer entryno = -1; - // handle the events, enable/disable the button, show the popup if button clicked - if ( UI::WidgetExists(`id("_cwm_firewall_details")) && UI::WidgetExists(`id("_cwm_open_firewall")) ) - CWMFirewallInterfaces::OpenFirewallHandle (fw_cwm_widget, "", $[ "ID" : widget ]); - if ( UI::WidgetExists(`id(`fstable)) ) - entryno = (integer) UI::QueryWidget(`id(`fstable), `CurrentItem); - - if (widget == `newbut) - { - map entry = GetFstabEntry (nil, (list) union (Nfs::non_nfs_entries, nfs_entries)); - - if (entry != nil) - { - nfs_entries = add (nfs_entries, entry); - modify_line = entry; - EnableDisableButtons(); - - Nfs::SetModified(); - } - - UI::ChangeWidget (`id(`fstable), `Items, FstabTableItems (nfs_entries)); - } - else if (widget == `editbut) - { - integer count = 0; - map entry = GetFstabEntry (nfs_entries[entryno]:$[], // Default values - (list) union (Nfs::non_nfs_entries, remove (nfs_entries, entryno))); - if (entry != nil) - { - integer count = 0; - nfs_entries = maplist(map ent, nfs_entries, ``{ - count = count+1; - if (count-1 != entryno) - return ent; - return entry; - }); - - modify_line = entry; - UI::ChangeWidget (`id(`fstable), `Items, FstabTableItems (nfs_entries)); - Nfs::SetModified(); - } - } - else if (widget == `delbut && size (nfs_entries) > 0) - { - map share = nfs_entries[entryno]: $[]; - if ( Popup::YesNo( sformat( _("Really delete %1?"), share["spec"]:"")) ) - { - modify_line = share; - nfs_entries = remove (nfs_entries, entryno); - UI::ChangeWidget (`id(`fstable), `Items, FstabTableItems (nfs_entries)); - EnableDisableButtons(); - - Nfs::SetModified(); - } - } - else if (widget == `enable_nfs4) - { - boolean enabled = (boolean) UI::QueryWidget(`id(`enable_nfs4), `Value); - UI::ChangeWidget( `id(`nfs4_domain), `Enabled, enabled); - Nfs::SetModified(); - } - else if ( widget == `settings ) - { - SaveFstabEntries( ); - UI::ReplaceWidget(`id(`rp), SettingsTab() ); - InitSettings(); - Wizard::SetHelpText( help_text2 ); - } - else if ( widget == `overview ) - { - SaveSettings( $[ "ID" : widget ] ); - UI::ReplaceWidget(`id(`rp), FstabTab() ); - InitFstabEntries(); - Wizard::SetHelpText( help_text1 ); - } - } - - /** - * NFS client dialog itselfs - * @return `back, `abort or `next - */ - define symbol FstabDialog () ``{ - Wizard::SetScreenShotName ("nfs-client-1-fstab"); - - nfs_entries = Nfs::nfs_entries; - - // dialog heading - Wizard::SetContents(_("NFS Client Configuration"), - MainDialogLayout(), help_text1, - false, - true); - //Wizard::HideBackButton(); - //Wizard::SetAbortButton(`abort, Label::CancelButton()); - - InitFstabEntries(); - - // Kludge, because a `Table still does not have a shortcut. - // Simple to solve here: there's only the table and buttons, - // so it is OK to always set focus to the table - UI::SetFocus (`id (`fstable)); - - map event = nil; - any ret = nil; - integer entryno = -1; - - do - { - event = UI::WaitForEvent (); - ret = event["ID"]:nil; - if (ret == `ok) - { - ret = `next; - } - else if (ret == `cancel) - { - ret = `abort; - } - else if (ret == `abort && Nfs::GetModified() && !Popup::ReallyAbort (true)) - { - ret = `again; - } - else - HandleEvent( ret ); - } - while (ret != `back && ret != `next && ret != `abort); - - if (ret == `next) - { - // grab current settings, store them to SuSEFirewall:: - if( UI::WidgetExists(`id(`fstable)) ) - SaveFstabEntries( ); - if( UI::WidgetExists(`id(`enable_nfs4)) ) - SaveSettings( event ); - - } - - Wizard::RestoreScreenShotName (); - return (symbol) ret; - } - -} diff --git a/src/include/nfs/wizards.rb b/src/include/nfs/wizards.rb new file mode 100644 index 0000000..9276aa2 --- /dev/null +++ b/src/include/nfs/wizards.rb @@ -0,0 +1,54 @@ +# encoding: utf-8 + +# File: include/nfs/wizards.ycp +# Package: Configuration of nfs +# Summary: Wizards definitions +# Authors: Martin Vidner +# +# $Id$ +module Yast + module NfsWizardsInclude + def initialize_nfs_wizards(include_target) + Yast.import "UI" + + textdomain "nfs" + + Yast.import "Sequencer" + Yast.import "Wizard" + + Yast.include include_target, "nfs/ui.rb" + end + + # Configuration of NFS client + # without Read and Write + # @return sequence result + def MainSequence + FstabDialog() + end + + # Whole configuration of NFS client + # @return sequence result + def NfsSequence + aliases = { + "read" => [lambda { ReadDialog() }, true], + "main" => lambda { MainSequence() }, + "write" => [lambda { WriteDialog() }, true] + } + + sequence = { + "ws_start" => "read", + "read" => { :abort => :abort, :next => "main" }, + "main" => { :abort => :abort, :next => "write" }, + "write" => { :abort => :abort, :next => :next } + } + + Wizard.OpenOKDialog + Wizard.SetDesktopTitleAndIcon("nfs") + + ret = Sequencer.Run(aliases, sequence) + + UI.CloseDialog + deep_copy(ret) + end + end +end diff --git a/src/include/nfs/wizards.ycp b/src/include/nfs/wizards.ycp deleted file mode 100644 index a407737..0000000 --- a/src/include/nfs/wizards.ycp +++ /dev/null @@ -1,67 +0,0 @@ -/** - * File: include/nfs/wizards.ycp - * Package: Configuration of nfs - * Summary: Wizards definitions - * Authors: Martin Vidner - * - * $Id$ - */ - -{ - -textdomain "nfs"; - -import "Sequencer"; -import "Wizard"; - -include "nfs/ui.ycp"; - -/** - * Configuration of NFS client - * without Read and Write - * @return sequence result - */ -any MainSequence () -{ - return FstabDialog (); -} - -/** - * Whole configuration of NFS client - * @return sequence result - */ -any NfsSequence () -{ - map aliases = $[ - "read" : [ ``( ReadDialog () ), true ], - "main" : ``( MainSequence () ), - "write" : [ ``( WriteDialog () ), true ] - ]; - - map sequence = $[ - "ws_start" : "read", - "read" : $[ - `abort : `abort, - `next : "main" - ], - "main" : $[ - `abort : `abort, - `next : "write" - ], - "write" : $[ - `abort : `abort, - `next : `next - ] - ]; - - Wizard::OpenOKDialog (); - Wizard::SetDesktopTitleAndIcon ("nfs"); - - any ret = Sequencer::Run (aliases, sequence); - - UI::CloseDialog (); - return ret; -} - -/* EOF */ -} diff --git a/src/modules/Nfs.rb b/src/modules/Nfs.rb new file mode 100644 index 0000000..4330707 --- /dev/null +++ b/src/modules/Nfs.rb @@ -0,0 +1,789 @@ +# encoding: utf-8 + +# File: +# Nfs.ycp +# +# Module: +# Configuration of nfs +# +# Summary: +# NFS client configuration data, I/O functions. +# +# Authors: +# Jan Holesovsky +# Dan Vesely +# Martin Vidner +# +# $Id$ +require "yast" + +module Yast + class NfsClass < Module + def main + + textdomain "nfs" + + Yast.import "FileUtils" + Yast.import "Mode" + Yast.import "NfsOptions" + Yast.import "Report" + Yast.import "Service" + Yast.import "Summary" + Yast.import "SuSEFirewall" + Yast.import "Progress" + Yast.import "PackageSystem" + Yast.import "PackagesProposal" + Yast.import "Wizard" + + Yast.include self, "nfs/routines.rb" + + + # default value of settings modified + @modified = false + + # Should fstab reading be skipped ? (yes if we're + # embedded in partitioner) + @skip_fstab = false + + # Required packages + @required_packages = ["nfs-client"] + + # eg.: [ $["spec": "moon:/cheese", file: "/mooncheese", "mntops": "defaults"], ...] + @nfs_entries = [] + + # Read only, intended for checking mount-point uniqueness. + @non_nfs_entries = [] + + @nfs4_enabled = nil + + @nfs_gss_enabled = nil + + @idmapd_domain = "" + + @portmapper = "" + + # list of created directories + @created_dirs = [] + end + + # Function sets internal variable, which indicates, that any + # settings were modified, to "true" + def SetModified + @modified = true + + nil + end + + # Functions which returns if the settings were modified + # @return [Boolean] settings were modified + def GetModified + @modified + end + + def ReadNfs4 + SCR.Read(path(".sysconfig.nfs.NFS4_SUPPORT")) == "yes" + end + + def ReadNfsGss + SCR.Read(path(".sysconfig.nfs.NFS_SECURITY_GSS")) == "yes" + end + + def ReadIdmapd + Convert.to_string(SCR.Read(path(".etc.idmapd_conf.value.General.Domain"))) + end + + def ValidateAyNfsEntry(entry) + entry = deep_copy(entry) + valid = true + Builtins.foreach(["server_path", "mount_point", "nfs_options"]) do |k| + if !Builtins.haskey(entry, k) + Builtins.y2error("Missing at Import: '%1'.", k) + valid = false + end + end + valid + end + + def GetOptionsAndEntriesSLE11(settings, global_options, entries) + settings = deep_copy(settings) + if Builtins.haskey(Ops.get(settings, 0, {}), "enable_nfs4") || + Builtins.haskey(Ops.get(settings, 0, {}), "idmapd_domain") + global_options.value = Ops.get(settings, 0, {}) + settings = Builtins.remove(settings, 0) + end + + entries.value = Convert.convert( + settings, + :from => "list ", + :to => "list >" + ) + + nil + end + + + def GetOptionsAndEntriesMap(settings, global_options, entries) + settings = deep_copy(settings) + global_options.value = Builtins.remove(settings, "nfs_entries") + entries.value = Ops.get_list(settings, "nfs_entries", []) + + nil + end + + # From settings (which is a list in SLE11 but a map in oS: bnc#820989), + # extract the options and the NFS fstab entries. + def GetOptionsAndEntries(any_settings, global_options, entries) + any_settings = deep_copy(any_settings) + # map: oS; + if Ops.is_map?(any_settings) + global_options_ref = arg_ref(global_options.value) + entries_ref = arg_ref(entries.value) + GetOptionsAndEntriesMap( + Convert.to_map(any_settings), + global_options_ref, + entries_ref + ) + global_options.value = global_options_ref.value + entries.value = entries_ref.value + elsif Ops.is(any_settings, "list ") + global_options_ref = arg_ref(global_options.value) + entries_ref = arg_ref(entries.value) + GetOptionsAndEntriesSLE11( + Convert.convert(any_settings, :from => "any", :to => "list "), + global_options_ref, + entries_ref + ) + global_options.value = global_options_ref.value + entries.value = entries_ref.value + else + Builtins.y2internal( + "Cannot happen, got neither a map nor a list: %1", + any_settings + ) + end + + nil + end + + # Fill in the defaults for AY profile entries. + def FillEntriesDefaults(entries) + entries = deep_copy(entries) + Builtins.maplist(entries) do |e| + #Backwards compatibility: with FaTE#302031, we support nfsv4 mounts + #thus we need to keep info on nfs version (v3 vs. v4) + #But older AY profiles might not contain this element + #so let's assume nfsv3 in that case (#395850) + Ops.set(e, "vfstype", "nfs") if !Builtins.haskey(e, "vfstype") + deep_copy(e) + end + end + + def ImportAny(settings) + settings = deep_copy(settings) + # ($) since oS-1x.x, settings was changed to be a map, + # which is incompatible with the sle profiles; + # it owuld be nice to make it compatible again + # whjich this code is readyu to, but the Autoyast engine isn't. + global_options = {} + entries = [] + global_options_ref = arg_ref(global_options) + entries_ref = arg_ref(entries) + GetOptionsAndEntries(settings, global_options_ref, entries_ref) + global_options = global_options_ref.value + entries = entries_ref.value + + return false if Builtins.find(entries) { |e| !ValidateAyNfsEntry(e) } != nil + + entries = FillEntriesDefaults(entries) + + @nfs4_enabled = Ops.get_boolean(global_options, "enable_nfs4") do + ReadNfs4() + end + @nfs_gss_enabled = Ops.get_boolean(global_options, "enable_nfs_gss") do + ReadNfsGss() + end + @idmapd_domain = Ops.get_string(global_options, "idmapd_domain") do + ReadIdmapd() + end + + # vfstype can override a missing enable_nfs4 + @nfs4_enabled = true if Builtins.find(entries) do |entry| + Ops.get_string(entry, "vfstype", "") == "nfs4" + end != nil + + @nfs_entries = Builtins.maplist(entries) do |entry| + { + "spec" => Ops.get_string(entry, "server_path", ""), + "file" => Ops.get_string(entry, "mount_point", ""), + "vfstype" => Ops.get_string(entry, "vfstype", ""), + "mntops" => Ops.get_string(entry, "nfs_options", "") + } + end + + true + end + + # Get all NFS configuration from a map. + # When called by nfs_auto (preparing autoinstallation data) + # the map may be empty. + # @param [Hash{String => Object}] settings a map($) of nfs_entries + # @return success + def Import(settings) + settings = deep_copy(settings) + ImportAny(settings) + end + + # Dump the NFS settings to a map, for autoinstallation use. + # @return a list of nfs entries. + def Export + settings = {} + + Ops.set(settings, "enable_nfs4", @nfs4_enabled) + Ops.set(settings, "enable_nfs_gss", @nfs_gss_enabled) + Ops.set(settings, "idmapd_domain", @idmapd_domain) + + entries = Builtins.maplist(@nfs_entries) do |entry| + { + "server_path" => Ops.get_string(entry, "spec", ""), + "mount_point" => Ops.get_string(entry, "file", ""), + "vfstype" => Ops.get_string(entry, "vfstype", ""), + "nfs_options" => Ops.get_string(entry, "mntops", "") + } + end + Ops.set(settings, "nfs_entries", entries) + deep_copy(settings) + end + + # ------------------------------------------------------------ + # Space escaping. + # This should be done by the agent, but any-agent sucks. + + # Escape spaces " " -> "\\040". + # @param [String] s a string or nil + # @return escaped string or nil + def EscapeSpaces1(s) + s == nil ? + nil : + Builtins.mergestring(Builtins.splitstring(s, " "), "\\040") + end + + # Escape spaces " " -> "\\040" in all values of all entries + # @param [Array Object>}] entries a list of maps, such as nfs_entries + # @return escaped entries + def EscapeSpaces(entries) + entries = deep_copy(entries) + Builtins.maplist(entries) { |entry| Builtins.mapmap(entry) do |key, value| + { + key => Ops.is_string?(value) ? + EscapeSpaces1(Convert.to_string(value)) : + value + } + end } + end + + # (like awk gsub, but return the result, not number of replacements) + # replaces from back! + # @param [String] regex regular expression to replace + # @param [String] replacement the replacement string + # @param [String] s where to replace + # @return the changed string + def gsub(regex, replacement, s) + temp = nil + while true + # argh, regexpsub logs an error if it cannot sub + break if !Builtins.regexpmatch(s, Ops.add(Ops.add(".*", regex), ".*")) + temp = Builtins.regexpsub( + s, + Ops.add(Ops.add("(.*)", regex), "(.*)"), + Ops.add(Ops.add("\\1", replacement), "\\2") + ) + break if temp == nil + s = temp + end + s + end + + # Un-escape spaces "\\040" -> " " + # @param [String] s string or nil + # @return escaped string or nil + def UnescapeSpaces1(s) + # escaped space, \040, is /\\040/ + # which is "\\\\040" + s == nil ? nil : gsub("\\\\040", " ", s) + end + + # Un-escape spaces "\\040" -> " " in all values of all entries + # @param [Array Object>}] entries a list of maps, such as nfs_entries + # @return escaped entries + def UnescapeSpaces(entries) + entries = deep_copy(entries) + Builtins.maplist(entries) { |entry| Builtins.mapmap(entry) do |key, value| + { + key => Ops.is_string?(value) ? + UnescapeSpaces1(Convert.to_string(value)) : + value + } + end } + end + + def FindPortmapper + #testsuite is dumb - it can't distinguish between the existence + #of two services - either both exists or both do not + return "portmap" if Mode.testsuite + Service.Find(["rpcbind", "portmap"]) + end + + # ------------------------------------------------------------ + + # Reads NFS settings from the SCR (.etc.fstab) + # @return true on success + def Read + #Read /etc/fstab if we're running standalone (otherwise, libstorage does the job) + if !@skip_fstab + fstab = Convert.convert( + SCR.Read(path(".etc.fstab")), + :from => "any", + :to => "list >" + ) + fstab = UnescapeSpaces(fstab) + Builtins.y2milestone("fstab: %1", fstab) + + # For simplicity, this leaves also the unused fileds in the maps. + @nfs_entries = Builtins.filter(fstab) do |entry| + Ops.get_string(entry, "vfstype", "") == "nfs" || + Ops.get_string(entry, "vfstype", "") == "nfs4" + end + @non_nfs_entries = Builtins.filter(fstab) do |entry| + Ops.get_string(entry, "vfstype", "") != "nfs" && + Ops.get_string(entry, "vfstype", "") != "nfs4" + end + end + + @nfs4_enabled = ReadNfs4() + @nfs_gss_enabled = ReadNfsGss() + @idmapd_domain = ReadIdmapd() + + progress_orig = Progress.set(false) + SuSEFirewall.Read + Progress.set(progress_orig) + + @portmapper = FindPortmapper() + #There is neither rpcbind nor portmap + if @portmapper == "" + #so let's install rpcbind (default since #423026) + @required_packages = Builtins.add(@required_packages, "rpcbind") + @portmapper = "rpcbind" + end + if @nfs4_enabled + @required_packages = Builtins.add(@required_packages, "nfsidmap") + end + + if Mode.installation + Builtins.foreach(@required_packages) do |p| + PackagesProposal.AddResolvables("yast2-nfs-client", :package, [p]) + end + else + if !PackageSystem.CheckAndInstallPackagesInteractive(@required_packages) + return false + end + end + + true + end + + # Writes the NFS client configuration without + # starting/stopping the service. + # Autoinstallation uses this and then calls SuSEconfig only once + # and starts the services together. + # (No parameters because it is too short to abort) + # @return true on success + def WriteOnly + # Merge with non-nfs entries from fstab: + fstab = Convert.convert( + SCR.Read(path(".etc.fstab")), + :from => "any", + :to => "list >" + ) + # unescape deferred for optimization + fstab = Builtins.filter(fstab) do |entry| + Ops.get_string(entry, "vfstype", "") != "nfs" && + Ops.get_string(entry, "vfstype", "") != "nfs4" + end + fstab = UnescapeSpaces(fstab) + + Builtins.foreach(@nfs_entries) do |entry| + fstab = Builtins.add( + fstab, + Convert.convert( + Builtins.union( + entry, + { "freq" => 0, "passno" => 0 } #"vfstype": "nfs", + ), + :from => "map", + :to => "map " + ) + ) + # create mount points + file = Ops.get_string(entry, "file", "") + if !Convert.to_boolean(SCR.Execute(path(".target.mkdir"), file)) + # error popup message + Report.Warning( + Builtins.sformat(_("Unable to create directory '%1'."), file) + ) + end + end + + Builtins.y2milestone("fstab: %1", fstab) + + SCR.Execute( + path(".target.bash"), + "/bin/cp $ORIG $BACKUP", + { "ORIG" => "/etc/fstab", "BACKUP" => "/etc/fstab.YaST2.save" } + ) + + fstab = EscapeSpaces(fstab) + if !SCR.Write(path(".etc.fstab"), fstab) + # error popup message + Report.Error( + _( + "Unable to write to /etc/fstab.\n" + + "No changes will be made to the\n" + + "the NFS client configuration.\n" + ) + ) + return false + end + + @portmapper = FindPortmapper() + if Builtins.size(@nfs_entries) != 0 + Service.Enable(@portmapper) + Service.Enable("nfs") + # #36737: it just runs sm_notify at boot time + # replaces rpc.statd + Service.Enable("nfsboot") + end + + if @nfs4_enabled == true + SCR.Write(path(".sysconfig.nfs.NFS4_SUPPORT"), "yes") + SCR.Write(path(".etc.idmapd_conf.value.General.Domain"), @idmapd_domain) + # flush the changes + SCR.Write(path(".etc.idmapd_conf"), nil) + elsif @nfs4_enabled == false + SCR.Write(path(".sysconfig.nfs.NFS4_SUPPORT"), "no") + end + SCR.Write( + path(".sysconfig.nfs.NFS_SECURITY_GSS"), + @nfs_gss_enabled ? "yes" : "no" + ) + + progress_orig = Progress.set(false) + SuSEFirewall.WriteOnly + Progress.set(progress_orig) + + true + end + + # Writes the NFS client configuration and starts/stops the service. + # (No parameters because it is too short to abort) + # @return true on success + def Write + if WriteOnly() + # dialog label + Progress.New( + _("Writing NFS Configuration"), + " ", + 2, + [ + # progress stage label + _("Stop services"), + # progress stage label + _("Start services") + ], + [ + # progress step label + _("Stopping services..."), + # progress step label + _("Starting services..."), + # final progress step label + _("Finished") + ], + "" + ) + + # help text + Wizard.RestoreHelp(_("Writing NFS client settings. Please wait...")) + + Progress.NextStage + + Service.Stop("nfs") + + Progress.NextStage + if Ops.greater_than(Builtins.size(@nfs_entries), 0) + if Service.Status(@portmapper) != 0 + # portmap must not be started if it is running already (see bug # 9999) + Service.Start(@portmapper) + end + + Service.Start("nfs") + # #74597: if all mounts are noauto, $? is 6 (unconfigured) + status = Service.Status("nfs") + if status != 0 && status != 6 + # error popup message + Report.Error(_("Unable to mount the NFS entries from /etc/fstab.")) + return false + end + end + + progress_orig = Progress.set(false) + SuSEFirewall.ActivateConfiguration + Progress.set(progress_orig) + + Progress.NextStage + return true + else + return false + end + end + + # Summary() + # @return Html formatted configuration summary + def Summary + summary = "" + nc = Summary.NotConfigured + # summary header + summary = Summary.AddHeader(summary, _("NFS Entries")) + entries = Builtins.size(@nfs_entries) + Builtins.y2milestone("Entries: %1", @nfs_entries) + # summary item, %1 is a number + configured = Builtins.sformat(_("%1 entries configured"), entries) + summary = Summary.AddLine( + summary, + Ops.greater_than(entries, 0) ? configured : nc + ) + summary + end + + + # Mount NFS directory + # @param [String] server remote server name + # @param [String] share name of the exported directory + # @param [String] mpoint mount point (can be empty or nil, in this case it will be mounted in temporary directory) + # @param [String] options mount options - e.g. "ro,hard,intr", see man nfs + # @param [String] type nfs type (nfs vs. nfsv4) - if empty, 'nfs' is used + # @return [String] directory where volume was mounted or nil if mount failed + + def Mount(server, share, mpoint, options, type) + return nil if Builtins.size(server) == 0 || Builtins.size(share) == 0 + + # check if options are valid + if Ops.greater_than(Builtins.size(options), 0) + if NfsOptions.validate(options) != "" + Builtins.y2warning("invalid mount options: %1", options) + return nil + end + end + + # mount to temporary directory if mpoint is nil + if mpoint == nil + tmpdir = Convert.to_string(SCR.Read(path(".target.tmpdir"))) + + if tmpdir == nil || tmpdir == "" + Builtins.y2security("Warning: using /tmp directory!") + tmpdir = "/tmp" + end + + mpoint = Ops.add( + Ops.add(tmpdir, "/nfs"), + Builtins.sformat("%1", Builtins.size(@created_dirs)) + ) # use num to allow parallel mounts + end + + # check mount point + if CheckPath(mpoint) == false + # mount point is not valid + Builtins.y2warning("invalid mount point: %1", mpoint) + return nil + end + + portmapper = FindPortmapper() + # check whether portmapper is installed + if IsPortmapperInstalled(portmapper) == false + Builtins.y2warning("Neither rpcbind nor portmap is installed") + return nil + end + + + # start portmapper if it isn't running + if Service.Status(portmapper) != 0 + if Service.Start(portmapper) == false + Builtins.y2warning("%1 cannot be started", portmapper) + return nil + end + end + + # create mount point if it doesn't exist + if SCR.Read(path(".target.dir"), mpoint) == nil + if !Convert.to_boolean(SCR.Execute(path(".target.mkdir"), mpoint)) + Builtins.y2warning("cannot create mount point %1", mpoint) + return nil + end + + # remember name of created directory + @created_dirs = Builtins.add(@created_dirs, mpoint) + end + + # build mount command + command = Builtins.sformat( + "/bin/mount %1 %2 %3:%4 %5", + Ops.greater_than(Builtins.size(options), 0) ? + Ops.add("-o ", options) : + "", + Ops.add("-t ", Ops.greater_than(Builtins.size(type), 0) ? type : "nfs"), + server, + share, + mpoint + ) + + # execute mount command + SCR.Execute(path(".target.bash"), command) == 0 ? mpoint : nil + end + + # Unmount NFS directory from the system + # @param [String] mpoint NFS mount point to unmount + # @return [Boolean] true on success + def Unmount(mpoint) + return false if Builtins.size(mpoint) == 0 + + # unmount directory if it's NFS mountpoint + mounts = Convert.convert( + SCR.Read(path(".proc.mounts")), + :from => "any", + :to => "list >" + ) + found = false + + Builtins.foreach(mounts) do |m| + type = Ops.get_string(m, "vfstype") + file = Ops.get_string(m, "file") + found = true if (type == "nfs" || type == "nfs4") && file == mpoint + end + + + if found + command = Builtins.sformat("/bin/umount %1", mpoint) + + return false if SCR.Execute(path(".target.bash"), command) != 0 + else + Builtins.y2warning("%1 is not NFS mount point", mpoint) + return false + end + + # if the directory was created by Mount call and it is empty then remove it + if Builtins.contains(@created_dirs, mpoint) && + SCR.Read(path(".target.dir"), mpoint) == [] + command = Builtins.sformat("/bin/rmdir %1", mpoint) + + return false if SCR.Execute(path(".target.bash"), command) != 0 + + # remove directory from list + @created_dirs = Builtins.filter(@created_dirs) { |d| d != mpoint } + end + + true + end + + # Return required packages for auto-installation + # @return [Hash] of packages to be installed and to be removed + def AutoPackages + { "install" => @required_packages, "remove" => [] } + end + + # Probe the LAN for NFS servers. + # Uses RPC broadcast to mountd. + # @return a list of hostnames + def ProbeServers + #newer, shinier, better rpcinfo from rpcbind (#450056) + prog_name = "/sbin/rpcinfo" + delim = "" + + #fallback from glibc (uses different field separators, grr :( ) + if !FileUtils.Exists(prog_name) + prog_name = "/usr/sbin/rpcinfo" + delim = "-d ' ' " + end + + # #71064 + # this works also if ICMP broadcasts are ignored + cmd = Ops.add( + Ops.add(Ops.add(prog_name, " -b mountd 1 | cut "), delim), + "-f 2 | sort -u" + ) + out = Convert.to_map(SCR.Execute(path(".target.bash_output"), cmd)) + hosts = Builtins.filter( + Builtins.splitstring(Ops.get_string(out, "stdout", ""), "\n") + ) { |s| s != "" } + deep_copy(hosts) + end + + # Probe a server for its exports. + # @param [String] server IP or hostname + # @param [Boolean] v4 Use NFSv4? + # @return a list of exported paths + def ProbeExports(server, v4) + dirs = [] + + # showmounts does not work for nfsv4 (#466454) + if v4 + tmpdir = Mount(server, "/", nil, "ro", "nfs4") + + # This is completely stupid way how to explore what can be mounted + # and I even don't know if it is correct. Maybe 'find tmpdir -xdev -type d' + # should be used instead. No clue :( + dirs = Builtins.maplist( + Convert.convert( + SCR.Read(path(".target.dir"), tmpdir), + :from => "any", + :to => "list " + ) + ) { |dirent| Ops.add("/", dirent) } + dirs = Builtins.prepend(dirs, "/") + Unmount(tmpdir) + else + dirs = Convert.convert( + SCR.Read(path(".net.showexports"), server), + :from => "any", + :to => "list " + ) + end + + dirs = ["internal error"] if dirs == nil + deep_copy(dirs) + end + + publish :variable => :modified, :type => "boolean" + publish :variable => :skip_fstab, :type => "boolean" + publish :function => :SetModified, :type => "void ()" + publish :function => :GetModified, :type => "boolean ()" + publish :variable => :required_packages, :type => "list " + publish :variable => :nfs_entries, :type => "list >" + publish :variable => :non_nfs_entries, :type => "list " + publish :variable => :nfs4_enabled, :type => "boolean" + publish :variable => :nfs_gss_enabled, :type => "boolean" + publish :variable => :idmapd_domain, :type => "string" + publish :function => :Import, :type => "boolean (map )" + publish :function => :Export, :type => "map ()" + publish :function => :FindPortmapper, :type => "string ()" + publish :function => :Read, :type => "boolean ()" + publish :function => :WriteOnly, :type => "boolean ()" + publish :function => :Write, :type => "boolean ()" + publish :function => :Summary, :type => "string ()" + publish :function => :Mount, :type => "string (string, string, string, string, string)" + publish :function => :Unmount, :type => "boolean (string)" + publish :function => :AutoPackages, :type => "map ()" + publish :function => :ProbeServers, :type => "list ()" + publish :function => :ProbeExports, :type => "list (string, boolean)" + end + + Nfs = NfsClass.new + Nfs.main +end diff --git a/src/modules/Nfs.ycp b/src/modules/Nfs.ycp deleted file mode 100644 index 2163b4f..0000000 --- a/src/modules/Nfs.ycp +++ /dev/null @@ -1,753 +0,0 @@ -/** - * File: - * Nfs.ycp - * - * Module: - * Configuration of nfs - * - * Summary: - * NFS client configuration data, I/O functions. - * - * Authors: - * Jan Holesovsky - * Dan Vesely - * Martin Vidner - * - * $Id$ - */ - -{ - module "Nfs"; - - textdomain "nfs"; - - import "FileUtils"; - import "Mode"; - import "NfsOptions"; - import "Report"; - import "Service"; - import "Summary"; - import "SuSEFirewall"; - import "Progress"; - import "PackageSystem"; - import "PackagesProposal"; - import "Wizard"; - - include "nfs/routines.ycp"; - - - /* default value of settings modified */ - global boolean modified = false; - - /* Should fstab reading be skipped ? (yes if we're - embedded in partitioner) */ - global boolean skip_fstab = false; - - /** - * Function sets internal variable, which indicates, that any - * settings were modified, to "true" - */ - global define void SetModified () { - modified = true; - } - - /** - * Functions which returns if the settings were modified - * @return boolean settings were modified - */ - global define boolean GetModified () { - return modified; - } - - /** - * Required packages - */ - global list required_packages = [ "nfs-client" ]; - - /** - * eg.: [ $["spec": "moon:/cheese", file: "/mooncheese", "mntops": "defaults"], ...] - */ - global list > nfs_entries = []; - - /** - * Read only, intended for checking mount-point uniqueness. - */ - global list non_nfs_entries = []; - - global boolean nfs4_enabled = nil; - - global boolean nfs_gss_enabled = nil; - - global string idmapd_domain = ""; - - string portmapper = ""; - - // list of created directories - list created_dirs = []; - - boolean ReadNfs4() { - return SCR::Read(.sysconfig.nfs.NFS4_SUPPORT) == "yes"; - } - - boolean ReadNfsGss () { - return SCR::Read(.sysconfig.nfs.NFS_SECURITY_GSS) == "yes"; - } - - string ReadIdmapd() { - return (string) SCR::Read(.etc.idmapd_conf.value.General.Domain); - } - - boolean ValidateAyNfsEntry(map entry) { - boolean valid = true; - foreach (string k, ["server_path", "mount_point", "nfs_options"], - { - if (! haskey (entry, k)) - { - y2error ("Missing at Import: '%1'.", k); - valid = false; - } - }); - return valid; - } - - void GetOptionsAndEntriesSLE11(list settings, map & global_options, list > & entries) { - if (haskey (settings[0]:$[], "enable_nfs4") || - haskey (settings[0]:$[], "idmapd_domain")) { - global_options = settings[0]:$[]; - settings = remove(settings, 0); - } - - entries = (list >) settings; - } - - - void GetOptionsAndEntriesMap(map settings, map & global_options, list > & entries) { - global_options = remove(settings, "nfs_entries"); - entries = (list >) settings["nfs_entries"]:[]; - } - - /** - * From settings (which is a list in SLE11 but a map in oS: bnc#820989), - * extract the options and the NFS fstab entries. - */ - void GetOptionsAndEntries(any any_settings, map & global_options, list > & entries) { - // map: oS; - if (is(any_settings, map)) { - GetOptionsAndEntriesMap((map) any_settings, global_options, entries); - } - else if (is(any_settings, list)) { - GetOptionsAndEntriesSLE11((list) any_settings, global_options, entries); - } - else { - y2internal("Cannot happen, got neither a map nor a list: %1", any_settings); - } - } - - /** - * Fill in the defaults for AY profile entries. - */ - list > FillEntriesDefaults(list > entries) { - return maplist(map e, entries, { - //Backwards compatibility: with FaTE#302031, we support nfsv4 mounts - //thus we need to keep info on nfs version (v3 vs. v4) - //But older AY profiles might not contain this element - //so let's assume nfsv3 in that case (#395850) - if ( !haskey(e, "vfstype") ) - { - e["vfstype"] = "nfs"; - } - return e; - }); - } - - boolean ImportAny (any settings) { - // ($) since oS-1x.x, settings was changed to be a map, - // which is incompatible with the sle profiles; - // it owuld be nice to make it compatible again - // whjich this code is readyu to, but the Autoyast engine isn't. - map global_options = $[]; - list > entries = []; - GetOptionsAndEntries(settings, global_options, entries); - - if (find(map e, entries, ``(! ValidateAyNfsEntry(e)) ) != nil) { - return false; - } - - entries = FillEntriesDefaults(entries); - - nfs4_enabled = global_options["enable_nfs4"]:ReadNfs4(); - nfs_gss_enabled = global_options["enable_nfs_gss"]:ReadNfsGss(); - idmapd_domain = global_options["idmapd_domain"]:ReadIdmapd(); - - // vfstype can override a missing enable_nfs4 - if (find(map entry, entries, ``(entry["vfstype"]:"" == "nfs4")) != nil) { - nfs4_enabled = true; - } - - nfs_entries = maplist(map entry, entries, ``( - $[ - "spec": entry["server_path"]:"", - "file": entry["mount_point"]:"", - "vfstype": entry["vfstype"]:"", - "mntops": entry["nfs_options"]:"" - ] - )); - - return true; - } - - /** - * Get all NFS configuration from a map. - * When called by nfs_auto (preparing autoinstallation data) - * the map may be empty. - * @param settings a map($) of nfs_entries - * @return success - */ - global boolean Import (map settings) { - return ImportAny(settings); - } - - /** - * Dump the NFS settings to a map, for autoinstallation use. - * @return a list of nfs entries. - */ - global define map Export () ``{ - map settings = $[]; - - settings["enable_nfs4"] = nfs4_enabled; - settings["enable_nfs_gss"] = nfs_gss_enabled; - settings["idmapd_domain"] = idmapd_domain; - - list entries = maplist(map entry, nfs_entries, ``{ - return($[ - "server_path":entry["spec"]:"", - "mount_point":entry["file"]:"", - "vfstype" :entry["vfstype"]:"", - "nfs_options":entry["mntops"]:"" - ]); - }); - settings["nfs_entries"]= entries; - return settings; - } - - /* ------------------------------------------------------------ */ - // Space escaping. - // This should be done by the agent, but any-agent sucks. - - /** - * Escape spaces " " -> "\\040". - * @param s a string or nil - * @return escaped string or nil - */ - define string EscapeSpaces1 (string s) ``{ - return s == nil ? nil : mergestring (splitstring (s, " "), "\\040"); - } - - /** - * Escape spaces " " -> "\\040" in all values of all entries - * @param entries a list of maps, such as nfs_entries - * @return escaped entries - */ - define list > EscapeSpaces (list > entries) ``{ - return maplist (map entry, entries, - ``(mapmap (string key, any value, entry, ``( - $[ key : - (is (value, string)? - EscapeSpaces1 ((string) value): value)] - )) - )); - } - - /** - * (like awk gsub, but return the result, not number of replacements) - * replaces from back! - * @param regex regular expression to replace - * @param replacement the replacement string - * @param s where to replace - * @return the changed string - */ - define string gsub (string regex, string replacement, string s) ``{ - string temp = nil; - while (true) - { - // argh, regexpsub logs an error if it cannot sub - if (! regexpmatch (s, ".*" + regex + ".*")) - { - break; - } - temp = regexpsub (s, "(.*)"+regex+"(.*)", "\\1"+replacement+"\\2"); - if (temp == nil) - { - break; - } - s = temp; - } - return s; - } - - /** - * Un-escape spaces "\\040" -> " " - * @param s string or nil - * @return escaped string or nil - */ - define string UnescapeSpaces1 (string s) ``{ - // escaped space, \040, is /\\040/ - // which is "\\\\040" - return s == nil ? nil : gsub ("\\\\040", " ", s); - } - - /** - * Un-escape spaces "\\040" -> " " in all values of all entries - * @param entries a list of maps, such as nfs_entries - * @return escaped entries - */ - define list > UnescapeSpaces (list > entries) ``{ - return maplist (map entry, entries, - ``( mapmap (string key, any value, entry, ``( - $[ key: - (is (value, string)? - UnescapeSpaces1 ((string) value): value)] - )) - )); - } - - global string FindPortmapper() { - //testsuite is dumb - it can't distinguish between the existence - //of two services - either both exists or both do not - if (Mode::testsuite()) - return "portmap"; - return Service::Find( ["rpcbind", "portmap" ] ); - } - - /* ------------------------------------------------------------ */ - - /** - * Reads NFS settings from the SCR (.etc.fstab) - * @return true on success - */ - global define boolean Read () ``{ - - //Read /etc/fstab if we're running standalone (otherwise, libstorage does the job) - if( !skip_fstab ) - { - list > fstab = (list >) SCR::Read (.etc.fstab); - fstab = UnescapeSpaces (fstab); - y2milestone ("fstab: %1", fstab); - - // For simplicity, this leaves also the unused fileds in the maps. - nfs_entries = filter (map entry, fstab, ``{ - return (entry["vfstype"]:"" == "nfs" || entry["vfstype"]:"" == "nfs4"); - }); - non_nfs_entries = filter (map entry, fstab, ``{ - return (entry["vfstype"]:"" != "nfs" && entry["vfstype"]:"" != "nfs4"); - }); - } - - nfs4_enabled = ReadNfs4(); - nfs_gss_enabled = ReadNfsGss(); - idmapd_domain = ReadIdmapd(); - - boolean progress_orig = Progress::set(false); - SuSEFirewall::Read (); - Progress::set(progress_orig); - - portmapper = FindPortmapper(); - //There is neither rpcbind nor portmap - if ( portmapper == "" ) - { - //so let's install rpcbind (default since #423026) - required_packages = add( required_packages, "rpcbind" ); - portmapper = "rpcbind"; - } - if (nfs4_enabled) - required_packages = add( required_packages, "nfsidmap"); - - if (Mode::installation()) - { - foreach (string p, required_packages, - { - PackagesProposal::AddResolvables ("yast2-nfs-client", `package, [p]); - }); - } - else - { - if ( !PackageSystem::CheckAndInstallPackagesInteractive( required_packages ) ) - return false; - } - - return true; - } - - /** - * Writes the NFS client configuration without - * starting/stopping the service. - * Autoinstallation uses this and then calls SuSEconfig only once - * and starts the services together. - * (No parameters because it is too short to abort) - * @return true on success - */ - global define boolean WriteOnly () ``{ - // Merge with non-nfs entries from fstab: - list > fstab = (list >) SCR::Read (.etc.fstab); - // unescape deferred for optimization - fstab = filter (map entry, fstab, ``{ - return ( entry["vfstype"]:"" != "nfs" && entry["vfstype"]:"" != "nfs4"); - }); - fstab = UnescapeSpaces (fstab); - - foreach (map entry, nfs_entries, ``{ - fstab = add (fstab, (map)union (entry, $[/*"vfstype": "nfs",*/ "freq": 0, "passno": 0])); - - // create mount points - string file = entry["file"]:""; - if (!(boolean) SCR::Execute (.target.mkdir, file)) - { - // error popup message - Report::Warning (sformat (_("Unable to create directory '%1'."), file)); - } - }); - - y2milestone ("fstab: %1", fstab); - - SCR::Execute (.target.bash, "/bin/cp $ORIG $BACKUP", $["ORIG" : "/etc/fstab", "BACKUP" : "/etc/fstab.YaST2.save"]); - - fstab = EscapeSpaces (fstab); - if (!SCR::Write(.etc.fstab, fstab)) - { - // error popup message - Report::Error (_("Unable to write to /etc/fstab. -No changes will be made to the -the NFS client configuration.\n")); - return false; - } - - portmapper = FindPortmapper(); - if (size (nfs_entries) != 0) - { - Service::Enable( portmapper ); - Service::Enable("nfs"); - // #36737: it just runs sm_notify at boot time - // replaces rpc.statd - Service::Enable("nfsboot"); - } - - if(nfs4_enabled == true) - { - SCR::Write(.sysconfig.nfs.NFS4_SUPPORT,"yes"); - SCR::Write(.etc.idmapd_conf.value.General.Domain, idmapd_domain); - // flush the changes - SCR::Write(.etc.idmapd_conf, nil); - } - else if (nfs4_enabled == false) - { - SCR::Write(.sysconfig.nfs.NFS4_SUPPORT,"no"); - } - SCR::Write( .sysconfig.nfs.NFS_SECURITY_GSS, nfs_gss_enabled ? "yes" : "no"); - - boolean progress_orig = Progress::set (false); - SuSEFirewall::WriteOnly (); - Progress::set (progress_orig); - - return true; - } - - /** - * Writes the NFS client configuration and starts/stops the service. - * (No parameters because it is too short to abort) - * @return true on success - */ - global define boolean Write () ``{ - if (WriteOnly ()) - { - // dialog label - Progress::New (_("Writing NFS Configuration"), " ", 2, [ - // progress stage label - _("Stop services"), - // progress stage label - _("Start services"), - ], [ - // progress step label - _("Stopping services..."), - // progress step label - _("Starting services..."), - // final progress step label - _("Finished") ], - "" ); - - // help text - Wizard::RestoreHelp(_("Writing NFS client settings. Please wait...")); - - Progress::NextStage (); - - Service::Stop("nfs"); - - Progress::NextStage (); - if (size (nfs_entries) > 0) - { - if (Service::Status ( portmapper ) != 0) - { - // portmap must not be started if it is running already (see bug # 9999) - Service::Start( portmapper ); - } - - Service::Start("nfs"); - // #74597: if all mounts are noauto, $? is 6 (unconfigured) - integer status = Service::Status("nfs"); - if (status != 0 && status != 6) - { - // error popup message - Report::Error (_("Unable to mount the NFS entries from /etc/fstab.")); - return false; - } - } - - boolean progress_orig = Progress::set (false); - SuSEFirewall::ActivateConfiguration (); - Progress::set (progress_orig); - - Progress::NextStage (); - return true; - } - else - { - return false; - } - } - - /** - * Summary() - * @return Html formatted configuration summary - */ - global define string Summary () ``{ - string summary = ""; - string nc = Summary::NotConfigured (); - // summary header - summary = Summary::AddHeader(summary, _("NFS Entries")); - integer entries = size(nfs_entries); - y2milestone("Entries: %1", nfs_entries); - // summary item, %1 is a number - string configured = sformat(_("%1 entries configured"), entries); - summary = Summary::AddLine(summary, (entries>0) ? configured : nc); - return summary; - } - - - /** - * Mount NFS directory - * @param server remote server name - * @param share name of the exported directory - * @param mpoint mount point (can be empty or nil, in this case it will be mounted in temporary directory) - * @param options mount options - e.g. "ro,hard,intr", see man nfs - * @param type nfs type (nfs vs. nfsv4) - if empty, 'nfs' is used - * @return string directory where volume was mounted or nil if mount failed - */ - - global define string Mount(string server, string share, string mpoint, string options, string type) ``{ - - if (size(server) == 0 || size(share) == 0) - { - return nil; - } - - // check if options are valid - if (size(options) > 0) - { - if (NfsOptions::validate(options) != "") - { - y2warning("invalid mount options: %1", options); - return nil; - } - } - - // mount to temporary directory if mpoint is nil - if (mpoint == nil) - { - string tmpdir = (string) SCR::Read(.target.tmpdir); - - if (tmpdir == nil || tmpdir == "") - { - y2security("Warning: using /tmp directory!"); - tmpdir = "/tmp"; - } - - mpoint = tmpdir + "/nfs" + sformat("%1", size(created_dirs)); // use num to allow parallel mounts - } - - // check mount point - if (CheckPath(mpoint) == false) - { - // mount point is not valid - y2warning("invalid mount point: %1", mpoint); - return nil; - } - - string portmapper = FindPortmapper(); - // check whether portmapper is installed - if (IsPortmapperInstalled( portmapper ) == false) - { - y2warning("Neither rpcbind nor portmap is installed"); - return nil; - } - - - // start portmapper if it isn't running - if (Service::Status( portmapper ) != 0) - { - if (Service::Start( portmapper ) == false) - { - y2warning("%1 cannot be started", portmapper); - return nil; - } - } - - // create mount point if it doesn't exist - if (SCR::Read(.target.dir, mpoint) == nil) - { - if (!(boolean) SCR::Execute(.target.mkdir, mpoint)) - { - y2warning("cannot create mount point %1", mpoint); - return nil; - } - - // remember name of created directory - created_dirs = add(created_dirs, mpoint); - } - - // build mount command - string command = sformat("/bin/mount %1 %2 %3:%4 %5", (size(options) > 0) ? "-o " + options : "", - "-t " + (size(type) > 0 ? type : "nfs"), - server, share, mpoint); - - // execute mount command - return (SCR::Execute(.target.bash, command) == 0) ? mpoint : nil; - } - - /** - * Unmount NFS directory from the system - * @param mpoint NFS mount point to unmount - * @return boolean true on success - */ - global define boolean Unmount(string mpoint) ``{ - if (size(mpoint) == 0) - { - return false; - } - - // unmount directory if it's NFS mountpoint - list > mounts = (list >) SCR::Read(.proc.mounts); - boolean found = false; - - foreach(map m, mounts, - ``{ - string type = (string) (m["vfstype"]:nil); - string file = (string) (m["file"]:nil); - - if ( (type == "nfs" || type == "nfs4") && file == mpoint) - { - found = true; - } - } - ); - - if (found) - { - string command = sformat("/bin/umount %1", mpoint); - - if (SCR::Execute(.target.bash, command) != 0) - { - return false; - } - } - else - { - y2warning("%1 is not NFS mount point", mpoint); - return false; - } - - // if the directory was created by Mount call and it is empty then remove it - if (contains(created_dirs, mpoint) && SCR::Read(.target.dir, mpoint) == []) - { - string command = sformat("/bin/rmdir %1", mpoint); - - if (SCR::Execute(.target.bash, command) != 0) - { - return false; - } - - // remove directory from list - created_dirs = filter(string d, created_dirs, ``(d != mpoint)); - } - - return true; - } - - /** - * Return required packages for auto-installation - * @return map of packages to be installed and to be removed - */ - global define map AutoPackages() ``{ - return ($["install": required_packages, "remove": []]); - - } - - /** - * Probe the LAN for NFS servers. - * Uses RPC broadcast to mountd. - * @return a list of hostnames - */ - global define list ProbeServers() { - //newer, shinier, better rpcinfo from rpcbind (#450056) - string prog_name = "/sbin/rpcinfo"; - string delim = ""; - - //fallback from glibc (uses different field separators, grr :( ) - if( !FileUtils::Exists(prog_name) ) - { - prog_name = "/usr/sbin/rpcinfo"; - delim = "-d ' ' "; - } - - // #71064 - // this works also if ICMP broadcasts are ignored - string cmd = prog_name + " -b mountd 1 | cut " + delim + "-f 2 | sort -u"; - map out = (map) SCR::Execute (.target.bash_output, cmd); - list hosts = filter (string s, splitstring (out["stdout"]:"", "\n"), ``( s != "")); - return hosts; - } - - /** - * Probe a server for its exports. - * @param server IP or hostname - * @param v4 Use NFSv4? - * @return a list of exported paths - */ - global list ProbeExports(string server, boolean v4) { - list dirs = []; - - // showmounts does not work for nfsv4 (#466454) - if (v4) - { - string tmpdir = Mount(server, "/", nil, "ro", "nfs4"); - - // This is completely stupid way how to explore what can be mounted - // and I even don't know if it is correct. Maybe 'find tmpdir -xdev -type d' - // should be used instead. No clue :( - dirs = maplist( string dirent, (list ) SCR::Read(.target.dir, tmpdir), { - return "/" + dirent; - }); - dirs = prepend(dirs, "/"); - Unmount( tmpdir ); - } - else - { - dirs = (list) SCR::Read (.net.showexports, server); - } - - if (dirs == nil) - { - dirs = ["internal error"]; - } - return dirs; - } - -} diff --git a/src/modules/NfsOptions.rb b/src/modules/NfsOptions.rb new file mode 100644 index 0000000..ca68e53 --- /dev/null +++ b/src/modules/NfsOptions.rb @@ -0,0 +1,211 @@ +# encoding: utf-8 + +require "yast" + +module Yast + class NfsOptionsClass < Module + def main + textdomain "nfs" + end + + # Parse to an internal representation: + # Simply split by commas, but "defaults" is represented by the empty list + # @param [String] options a fstab option string + # @return [Array] of individual options + def from_string(options) + options = "" if options == "defaults" + Builtins.splitstring(options, ",") + end + + # Convert list of individual options to a fstab option string + # @param [Array] option_list list of individual options + # @return a fstab option string + def to_string(option_list) + option_list = deep_copy(option_list) + options = Builtins.mergestring(option_list, ",") + options = "defaults" if options == "" + options + end + + # Checks the nfs options for /etc/fstab: + # nonempty, comma separated list of foo,nofoo,bar=baz (see nfs(5)) + # @param [String] options options + # @return a translated string with error message, emtpy string if ok + def validate(options) + # To translators: error popup + if Builtins.size(options) == 0 + return _("Empty option strings are not allowed.") + end + + option_list = from_string(options) + + # The options should be kept synced with the code that handles them, + # which is not an easy task, as there are many places: + # - util-linux.rpm + # man 8 mount + # https://git.kernel.org/?p=utils/util-linux/util-linux.git;a=history;f=libmount/src/optmap.c + # - nfs-client.rpm (nfs-utils.src.rpm) + # man 5 nfs + # http://git.linux-nfs.org/?p=steved/nfs-utils.git;a=history;f=utils/mount/nfsmount.c + # - kernel: fs/nfs/super.c + # http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=history;f=fs/nfs/super.c + # Note that minorversion in particular is mentioned only in the kernel + # but not in nfs-utils. WTF. + + # these can be negated by "no" + _NEGATABLE_OPTIONS = [ + "bg", + "fg", + "soft", + "hard", + "intr", + "posix", + "cto", + "ac", + "acl", + "lock", + "tcp", + "udp", + "rdirplus", + # these are common for all fs types + "atime", + "auto", + "dev", + "exec", + "group", + "owner", + "suid", + "user", + "users" + ] + _NEGATED_OPTIONS = Builtins.maplist(_NEGATABLE_OPTIONS) do |e| + Builtins.sformat("no%1", e) + end + + # these cannot be negated + # they are not nfs specific BTW + _SIMPLE_OPTIONS = [ + "defaults", + "async", + "sync", + "dirsync", + "ro", + "rw", + "remount", + "bind", + "rbind", + "_netdev" + ] + _OPTIONS_WITH_VALUE = [ + "rsize", + "wsize", + "timeo", + "retrans", + "acregmin", + "acregmax", + "acdirmin", + "acdirmin", + "acdirmax", + "actimeo", + "retry", + "namlen", + "port", + "proto", + "clientaddr", + "mountport", + "mounthost", + "mountprog", + "mountvers", + "nfsprog", + "nfsvers", + "vers", + "minorversion", + "sec" + ] + + # first fiter out non value options and its nooptions forms (see nfs(5)) + option_list = Builtins.filter(option_list) do |e| + !Builtins.contains(_NEGATABLE_OPTIONS, e) + end + option_list = Builtins.filter(option_list) do |e| + !Builtins.contains(_NEGATED_OPTIONS, e) + end + option_list = Builtins.filter(option_list) do |e| + !Builtins.contains(_SIMPLE_OPTIONS, e) + end + + error_message = "" + Builtins.foreach(option_list) do |opt| + opt_tuple = Builtins.splitstring(opt, "=") + key = Ops.get(opt_tuple, 0, "") + value = Ops.get(opt_tuple, 1, "") + # By now we have filtered out known options without values; + # so what is left is either unknown options, ... + # FIXME: this also triggers for "intr=bogus" + # because we should have considered '=' before the simple options + # FIXME "'" + foo + "'" used not to break translations; merge it. + if !Builtins.contains(_OPTIONS_WITH_VALUE, key) + # To translators: error popup + error_message = Builtins.sformat( + _("Unknown option: %1"), + Ops.add(Ops.add("'", key), "'") + ) + # ... or known ones with badly specified values + elsif Builtins.size(opt_tuple) != 2 + # To translators: error popup + error_message = Builtins.sformat( + _("Invalid option: %1"), + Ops.add(Ops.add("'", opt), "'") + ) + elsif value == "" + # To translators: error popup + error_message = Builtins.sformat( + _("Empty value for option: %1"), + Ops.add(Ops.add("'", key), "'") + ) + end + raise Break if error_message != "" + end + + error_message + end + + # FIXME: factor out get_nfs4(vfstype, options) (depending on n::o)! + # * @param options fstab option string + # * @return is version >= 4.1 enabled + def get_nfs41(options) + option_list = from_string(options) + + _ENABLED = "minorversion=1" + Builtins.contains(option_list, _ENABLED) + end + + # Add or remove minorversion=1 according to nfs41. + # FIXME vfstype=nfs4 is deprecated in favor of nfsvers=4 (aka vers=4) + # @param [String] options fstab option string + # @param [Boolean] nfs41 is version >= 4.1 enabled + # @return new fstab option string + def set_nfs41(options, nfs41) + # don't mutate the string unnecessarily + return options if get_nfs41(options) == nfs41 + + _ENABLED = "minorversion=1" + _DISABLED = "minorversion=0" + + option_list = from_string(options) + option_list = Builtins.filter(option_list) { |opt| opt != _ENABLED } + option_list = Builtins.filter(option_list) { |opt| opt != _DISABLED } + + option_list = Builtins.add(option_list, _ENABLED) if nfs41 + + to_string(option_list) + end + + publish :function => :validate, :type => "string (string)" + publish :function => :get_nfs41, :type => "boolean (string)" + publish :function => :set_nfs41, :type => "string (string, boolean)" + end + + NfsOptions = NfsOptionsClass.new + NfsOptions.main +end diff --git a/src/modules/NfsOptions.ycp b/src/modules/NfsOptions.ycp deleted file mode 100644 index cd039e2..0000000 --- a/src/modules/NfsOptions.ycp +++ /dev/null @@ -1,147 +0,0 @@ -{ - -module "NfsOptions"; -textdomain "nfs"; - -/** - * Parse to an internal representation: - * Simply split by commas, but "defaults" is represented by the empty list - * @param options a fstab option string - * @return list of individual options - */ -list from_string(string options) { - if (options == "defaults") { options = ""; } - return splitstring (options, ","); -} - -/** - * Convert list of individual options to a fstab option string - * @param option_list list of individual options - * @return a fstab option string - */ -string to_string(list option_list) { - string options = mergestring(option_list, ","); - if (options == "") { options = "defaults"; } - return options; -} - -/** - * Checks the nfs options for /etc/fstab: - * nonempty, comma separated list of foo,nofoo,bar=baz (see nfs(5)) - * @param options options - * @return a translated string with error message, emtpy string if ok - */ -global define string validate (string options) { - // To translators: error popup - if (size (options) == 0) return _("Empty option strings are not allowed."); - - list option_list = from_string(options); - - // The options should be kept synced with the code that handles them, - // which is not an easy task, as there are many places: - // - util-linux.rpm - // man 8 mount - // https://git.kernel.org/?p=utils/util-linux/util-linux.git;a=history;f=libmount/src/optmap.c - // - nfs-client.rpm (nfs-utils.src.rpm) - // man 5 nfs - // http://git.linux-nfs.org/?p=steved/nfs-utils.git;a=history;f=utils/mount/nfsmount.c - // - kernel: fs/nfs/super.c - // http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=history;f=fs/nfs/super.c - // Note that minorversion in particular is mentioned only in the kernel - // but not in nfs-utils. WTF. - - // these can be negated by "no" - const list NEGATABLE_OPTIONS = [ "bg", "fg", "soft", "hard", - "intr", "posix", "cto", "ac", "acl", - "lock", "tcp", "udp", "rdirplus", - // these are common for all fs types - "atime", "auto", "dev", "exec", "group", "owner", - "suid", "user", "users"]; - const list NEGATED_OPTIONS = maplist (string e, NEGATABLE_OPTIONS, ``(sformat ("no%1", e))); - - // these cannot be negated - // they are not nfs specific BTW - const list SIMPLE_OPTIONS = ["defaults", - "async", "sync", "dirsync", "ro", "rw", - "remount", "bind", "rbind", "_netdev", ]; - const list OPTIONS_WITH_VALUE = ["rsize", "wsize", - "timeo", "retrans", "acregmin", "acregmax", - "acdirmin", "acdirmin", "acdirmax", "actimeo", "retry", "namlen", - "port", "proto", "clientaddr", "mountport", "mounthost", - "mountprog", "mountvers", "nfsprog", "nfsvers", "vers", "minorversion", - "sec" ]; - - // first fiter out non value options and its nooptions forms (see nfs(5)) - option_list = filter (string e, option_list, ``(!contains (NEGATABLE_OPTIONS, e))); - option_list = filter (string e, option_list, ``(!contains (NEGATED_OPTIONS, e))); - option_list = filter (string e, option_list, ``(!contains (SIMPLE_OPTIONS, e))); - - string error_message = ""; - foreach (string opt, option_list, - { - list opt_tuple = splitstring (opt, "="); - string key = opt_tuple[0]:""; - string value = opt_tuple[1]:""; - // By now we have filtered out known options without values; - // so what is left is either unknown options, ... - // FIXME: this also triggers for "intr=bogus" - // because we should have considered '=' before the simple options - // FIXME "'" + foo + "'" used not to break translations; merge it. - if (!contains (OPTIONS_WITH_VALUE, key)) - // To translators: error popup - error_message = sformat (_("Unknown option: %1"), "'" + key + "'"); - // ... or known ones with badly specified values - else if (size (opt_tuple) != 2) - // To translators: error popup - error_message = sformat (_("Invalid option: %1"), "'" + opt + "'"); - else if (value == "") - // To translators: error popup - error_message = sformat (_("Empty value for option: %1"), "'" + key + "'"); - if (error_message != "") - break; - }); - - return error_message; -} - -/** -FIXME: factor out get_nfs4(vfstype, options) (depending on n::o)! - * @param options fstab option string - * @return is version >= 4.1 enabled - */ -global boolean get_nfs41(string options) { - list option_list = from_string(options); - - const string ENABLED = "minorversion=1"; - return contains(option_list, ENABLED); -} - -/** - * Add or remove minorversion=1 according to nfs41. - * FIXME vfstype=nfs4 is deprecated in favor of nfsvers=4 (aka vers=4) - * @param options fstab option string - * @param nfs41 is version >= 4.1 enabled - * @return new fstab option string - */ -global define string set_nfs41(string options, boolean nfs41) { - // don't mutate the string unnecessarily - if (get_nfs41(options) == nfs41) { - return options; - } - - const string ENABLED = "minorversion=1"; - const string DISABLED = "minorversion=0"; - - list option_list = from_string(options); - option_list = filter(string opt, option_list, ``( opt != ENABLED )); - option_list = filter(string opt, option_list, ``( opt != DISABLED )); - - if (nfs41) { - option_list = add(option_list, ENABLED); - } - - return to_string(option_list); -} - -/*EOF*/ -} diff --git a/testsuite/tests/autoyast.rb b/testsuite/tests/autoyast.rb new file mode 100644 index 0000000..ee45244 --- /dev/null +++ b/testsuite/tests/autoyast.rb @@ -0,0 +1,155 @@ +# encoding: utf-8 + +module Yast + class AutoyastClient < Client + def main + Yast.include self, "testsuite.rb" + @I_READ = { "target" => { "tmpdir" => "/tmp" } } + @I_WRITE = {} + @I_EXEC = {} + TESTSUITE_INIT([@I_READ, @I_WRITE, @I_EXEC], nil) + + @READ = { + "etc" => { "idmapd_conf" => "localdomain" }, + "sysconfig" => { + "nfs" => { "NFS4_SUPPORT" => "no", "NFS_SECURITY_GSS" => "no" } + } + } + + Yast.import "Nfs" + Yast.import "Assert" + + DUMP("Nfs::Import") + # --------- + DUMP("- basic, SLE11-SP2") + @entry1 = { + "server_path" => "data.example.com:/mirror", + "mount_point" => "/mirror", + "nfs_options" => "defaults" + } + + TEST(lambda { Nfs.ImportAny([@entry1]) }, [@READ, {}, {}], nil) + Assert.Equal(1, Builtins.size(Nfs.nfs_entries)) + Assert.Equal( + "data.example.com:/mirror", + Ops.get_string(Nfs.nfs_entries, [0, "spec"], "") + ) + + DUMP("-- and Export") + @ex = Nfs.Export + @e = Ops.get_list(@ex, "nfs_entries", []) + Assert.Equal(1, Builtins.size(@e)) + Assert.Equal(true, Builtins.haskey(@ex, "enable_nfs4")) + Assert.Equal(true, Builtins.haskey(@ex, "idmapd_domain")) + Assert.Equal( + "data.example.com:/mirror", + Ops.get_string(@e, [0, "server_path"], "") + ) + Assert.Equal("/mirror", Ops.get_string(@e, [0, "mount_point"], "")) + Assert.Equal("defaults", Ops.get_string(@e, [0, "nfs_options"], "")) + + # --------- + DUMP("- empty") + TEST(lambda { Nfs.ImportAny([]) }, [@READ, {}, {}], nil) + Assert.Equal(0, Builtins.size(Nfs.nfs_entries)) + + # --------- + DUMP("- invalid, missing basic data") + @entry_invalid = { "server_path" => "data.example.com:/mirror" } + + Nfs.ImportAny([@entry_invalid]) + Assert.Equal(0, Builtins.size(Nfs.nfs_entries)) + + # --------- + DUMP("- basic, SLE11-SP3") + @global_options = { + "enable_nfs4" => true, + "idmapd_domain" => "example.com" + } + TEST(lambda { Nfs.ImportAny([@global_options, @entry1]) }, [@READ, {}, {}], nil) + Assert.Equal(true, Nfs.nfs4_enabled) + Assert.Equal("example.com", Nfs.idmapd_domain) + Assert.Equal(1, Builtins.size(Nfs.nfs_entries)) + Assert.Equal( + "data.example.com:/mirror", + Ops.get_string(Nfs.nfs_entries, [0, "spec"], "") + ) + + DUMP("-- and Export") + @ex = Nfs.Export + @e = Ops.get_list(@ex, "nfs_entries", []) + Assert.Equal(1, Builtins.size(@e)) + Assert.Equal(true, Ops.get_boolean(@ex, "enable_nfs4", false)) + Assert.Equal("example.com", Ops.get_string(@ex, "idmapd_domain", "")) + Assert.Equal( + "data.example.com:/mirror", + Ops.get_string(@e, [0, "server_path"], "") + ) + Assert.Equal("/mirror", Ops.get_string(@e, [0, "mount_point"], "")) + Assert.Equal("defaults", Ops.get_string(@e, [0, "nfs_options"], "")) + + # --------- + DUMP("- NFSv4 via vfstype") + @global_options2 = { "idmapd_domain" => "example.com" } + @entry2 = { + "server_path" => "data.example.com:/mirror", + "mount_point" => "/mirror", + "nfs_options" => "defaults", + "vfstype" => "nfs4" + } + + TEST(lambda { Nfs.ImportAny([@global_options2, @entry2]) }, [@READ, {}, {}], nil) + + Assert.Equal(true, Nfs.nfs4_enabled) + Assert.Equal("example.com", Nfs.idmapd_domain) + Assert.Equal(1, Builtins.size(Nfs.nfs_entries)) + Assert.Equal( + "data.example.com:/mirror", + Ops.get_string(Nfs.nfs_entries, [0, "spec"], "") + ) + + DUMP("-- and Export") + @ex = Nfs.Export + @e = Ops.get_list(@ex, "nfs_entries", []) + Assert.Equal(1, Builtins.size(@e)) + Assert.Equal(true, Ops.get_boolean(@ex, "enable_nfs4", false)) + Assert.Equal("example.com", Ops.get_string(@ex, "idmapd_domain", "")) + Assert.Equal( + "data.example.com:/mirror", + Ops.get_string(@e, [0, "server_path"], "") + ) + Assert.Equal("/mirror", Ops.get_string(@e, [0, "mount_point"], "")) + Assert.Equal("defaults", Ops.get_string(@e, [0, "nfs_options"], "")) + + # --------- + DUMP("- with GSS") + @global_options = { + "enable_nfs4" => true, + "enable_nfs_gss" => true, + "idmapd_domain" => "example.com" + } + TEST(lambda { Nfs.ImportAny([@global_options, @entry1]) }, [@READ, {}, {}], nil) + # assertions shortened + Assert.Equal(true, Nfs.nfs_gss_enabled) + Assert.Equal(1, Builtins.size(Nfs.nfs_entries)) + Assert.Equal( + "data.example.com:/mirror", + Ops.get_string(Nfs.nfs_entries, [0, "spec"], "") + ) + + DUMP("-- and Export") + @ex = Nfs.Export + @e = Ops.get_list(@ex, "nfs_entries", []) + Assert.Equal(1, Builtins.size(@e)) + Assert.Equal(true, Ops.get_boolean(@ex, "enable_nfs_gss", false)) + Assert.Equal( + "data.example.com:/mirror", + Ops.get_string(@e, [0, "server_path"], "") + ) + + nil + end + end +end + +Yast::AutoyastClient.new.main diff --git a/testsuite/tests/autoyast.ycp b/testsuite/tests/autoyast.ycp deleted file mode 100644 index af0b093..0000000 --- a/testsuite/tests/autoyast.ycp +++ /dev/null @@ -1,153 +0,0 @@ -{ - include "testsuite.ycp"; - map I_READ = $[ - "target" : $[ - "tmpdir" : "/tmp", - ], - ]; - map I_WRITE = $[]; - map I_EXEC = $[]; - TESTSUITE_INIT ([I_READ, I_WRITE, I_EXEC], nil); - - map READ = $[ - "etc": $[ - "idmapd_conf" : "localdomain", - ], - "sysconfig": $[ - "nfs" : $[ - "NFS4_SUPPORT": "no", - "NFS_SECURITY_GSS": "no", - ], - ], - ]; - - import "Nfs"; - import "Assert"; - - DUMP("Nfs::Import"); - // --------- - DUMP("- basic, SLE11-SP2"); - map entry1 = $[ - "server_path": "data.example.com:/mirror", - "mount_point": "/mirror", - "nfs_options": "defaults" - ]; - - TEST (``( - Nfs::ImportAny([ entry1 ]) - ), [READ, $[], $[]], nil); - Assert::Equal(1, size(Nfs::nfs_entries)); - Assert::Equal("data.example.com:/mirror", Nfs::nfs_entries[0, "spec"]:""); - - DUMP("-- and Export"); - map ex = Nfs::Export(); - list e = ex["nfs_entries"]:[]; - Assert::Equal(1, size(e)); - Assert::Equal(true, haskey(ex, "enable_nfs4")); - Assert::Equal(true, haskey(ex, "idmapd_domain")); - Assert::Equal("data.example.com:/mirror", e[0, "server_path"]:""); - Assert::Equal("/mirror", e[0, "mount_point"]:""); - Assert::Equal("defaults", e[0, "nfs_options"]:""); - - // --------- - DUMP("- empty"); - TEST (``( - Nfs::ImportAny([]) - ), [READ, $[], $[]], nil); - Assert::Equal(0, size(Nfs::nfs_entries)); - - // --------- - DUMP("- invalid, missing basic data"); - map entry_invalid = $[ - "server_path": "data.example.com:/mirror", - ]; - - Nfs::ImportAny([ entry_invalid ]); - Assert::Equal(0, size(Nfs::nfs_entries)); - - // --------- - DUMP("- basic, SLE11-SP3"); - map global_options = $[ - "enable_nfs4": true, - "idmapd_domain": "example.com" - ]; - TEST (``( - Nfs::ImportAny([ - global_options, - entry1 - ]) - ), [READ, $[], $[]], nil); - Assert::Equal(true, Nfs::nfs4_enabled); - Assert::Equal("example.com", Nfs::idmapd_domain); - Assert::Equal(1, size(Nfs::nfs_entries)); - Assert::Equal("data.example.com:/mirror", Nfs::nfs_entries[0, "spec"]:""); - - DUMP("-- and Export"); - ex = Nfs::Export(); - e = ex["nfs_entries"]:[]; - Assert::Equal(1, size(e)); - Assert::Equal(true, ex["enable_nfs4"]:false); - Assert::Equal("example.com", ex["idmapd_domain"]:""); - Assert::Equal("data.example.com:/mirror", e[0, "server_path"]:""); - Assert::Equal("/mirror", e[0, "mount_point"]:""); - Assert::Equal("defaults", e[0, "nfs_options"]:""); - - // --------- - DUMP("- NFSv4 via vfstype"); - map global_options2 = $[ - "idmapd_domain": "example.com" - ]; - map entry2 = $[ - "server_path": "data.example.com:/mirror", - "mount_point": "/mirror", - "nfs_options": "defaults", - "vfstype": "nfs4" - ]; - - TEST (``( - Nfs::ImportAny([ - global_options2, - entry2 - ]) - ), [READ, $[], $[]], nil); - - Assert::Equal(true, Nfs::nfs4_enabled); - Assert::Equal("example.com", Nfs::idmapd_domain); - Assert::Equal(1, size(Nfs::nfs_entries)); - Assert::Equal("data.example.com:/mirror", Nfs::nfs_entries[0, "spec"]:""); - - DUMP("-- and Export"); - ex = Nfs::Export(); - e = ex["nfs_entries"]:[]; - Assert::Equal(1, size(e)); - Assert::Equal(true, ex["enable_nfs4"]:false); - Assert::Equal("example.com", ex["idmapd_domain"]:""); - Assert::Equal("data.example.com:/mirror", e[0, "server_path"]:""); - Assert::Equal("/mirror", e[0, "mount_point"]:""); - Assert::Equal("defaults", e[0, "nfs_options"]:""); - - // --------- - DUMP("- with GSS"); - global_options = $[ - "enable_nfs4": true, - "enable_nfs_gss": true, - "idmapd_domain": "example.com" - ]; - TEST (``( - Nfs::ImportAny([ - global_options, - entry1 - ]) - ), [READ, $[], $[]], nil); - // assertions shortened - Assert::Equal(true, Nfs::nfs_gss_enabled); - Assert::Equal(1, size(Nfs::nfs_entries)); - Assert::Equal("data.example.com:/mirror", Nfs::nfs_entries[0, "spec"]:""); - - DUMP("-- and Export"); - ex = Nfs::Export(); - e = ex["nfs_entries"]:[]; - Assert::Equal(1, size(e)); - Assert::Equal(true, ex["enable_nfs_gss"]:false); - Assert::Equal("data.example.com:/mirror", e[0, "server_path"]:""); -} diff --git a/testsuite/tests/escape.rb b/testsuite/tests/escape.rb new file mode 100644 index 0000000..4478e49 --- /dev/null +++ b/testsuite/tests/escape.rb @@ -0,0 +1,65 @@ +# encoding: utf-8 + +# Module: +# NFS client configuration +# +# Summary: +# Space escaping testuite +# +# Authors: +# Martin Vidner +# +# $Id$ +module Yast + class EscapeClient < Client + def main + # testedfiles: Nfs.ycp Testsuite.ycp + + Yast.include self, "testsuite.rb" + + @READ = { "target" => { "size" => 0 } } + @WRITE = {} + @EXEC = { "target" => { "bash_output" => {} } } + TESTSUITE_INIT([@READ, @WRITE, @EXEC], nil) + + Yast.import "Nfs" + + DUMP("Nfs::EscapeSpaces1 normative") + TEST(lambda { Nfs.EscapeSpaces1(nil) }, [], nil) + TEST(lambda { Nfs.EscapeSpaces1("") }, [], nil) + TEST(lambda { Nfs.EscapeSpaces1(" ") }, [], nil) + TEST(lambda { Nfs.EscapeSpaces1(" ") }, [], nil) + TEST(lambda { Nfs.EscapeSpaces1("nospaces") }, [], nil) + TEST(lambda { Nfs.EscapeSpaces1("one space") }, [], nil) + TEST(lambda { Nfs.EscapeSpaces1(" before, two, after ") }, [], nil) + + DUMP("Nfs::EscapeSpaces1 informative") + # weird characters + # TEST cuts it off at the newline :( + TEST(lambda { Nfs.EscapeSpaces1("'\"\\\n") }, [], nil) + # see how it works when applied multiple times + TEST(lambda { Nfs.EscapeSpaces1(Nfs.EscapeSpaces1(" ")) }, [], nil) + + + DUMP("Nfs::UnescapeSpaces1 normative") + TEST(lambda { Nfs.UnescapeSpaces1(nil) }, [], nil) + TEST(lambda { Nfs.UnescapeSpaces1("") }, [], nil) + TEST(lambda { Nfs.UnescapeSpaces1("\\040") }, [], nil) + TEST(lambda { Nfs.UnescapeSpaces1("\\040\\040") }, [], nil) + TEST(lambda { Nfs.UnescapeSpaces1("nospaces") }, [], nil) + TEST(lambda { Nfs.UnescapeSpaces1("one\\040space") }, [], nil) + TEST(lambda do + Nfs.UnescapeSpaces1("\\040before,\\040two,\\040\\040after\\040") + end, [], nil) + + DUMP("Nfs::UnescapeSpaces1 informative") + TEST(lambda { Nfs.UnescapeSpaces1("\\041\\") }, [], nil) + # see how it works when applied multiple times + TEST(lambda { Nfs.UnescapeSpaces1(Nfs.UnescapeSpaces1("\\040")) }, [], nil) + + nil + end + end +end + +Yast::EscapeClient.new.main diff --git a/testsuite/tests/escape.ycp b/testsuite/tests/escape.ycp deleted file mode 100644 index 374a2be..0000000 --- a/testsuite/tests/escape.ycp +++ /dev/null @@ -1,63 +0,0 @@ -/** - * Module: - * NFS client configuration - * - * Summary: - * Space escaping testuite - * - * Authors: - * Martin Vidner - * - * $Id$ - */ -{ - // testedfiles: Nfs.ycp Testsuite.ycp - - include "testsuite.ycp"; - - map READ = $[ - "target" : $[ - "size" : 0, - ], - ]; - map WRITE = $[]; - map EXEC = $[ - "target" : $[ - "bash_output" : $[], - ], - ]; - TESTSUITE_INIT ([READ, WRITE, EXEC], nil); - - import "Nfs"; - - DUMP ("Nfs::EscapeSpaces1 normative"); - TEST (``(Nfs::EscapeSpaces1 (nil)), [], nil); - TEST (``(Nfs::EscapeSpaces1 ("")), [], nil); - TEST (``(Nfs::EscapeSpaces1 (" ")), [], nil); - TEST (``(Nfs::EscapeSpaces1 (" ")), [], nil); - TEST (``(Nfs::EscapeSpaces1 ("nospaces")), [], nil); - TEST (``(Nfs::EscapeSpaces1 ("one space")), [], nil); - TEST (``(Nfs::EscapeSpaces1 (" before, two, after ")), [], nil); - - DUMP ("Nfs::EscapeSpaces1 informative"); - // weird characters - // TEST cuts it off at the newline :( - TEST (``(Nfs::EscapeSpaces1 ("'\"\\\n")), [], nil); - // see how it works when applied multiple times - TEST (``(Nfs::EscapeSpaces1 (Nfs::EscapeSpaces1 (" "))), [], nil); - - - DUMP ("Nfs::UnescapeSpaces1 normative"); - TEST (``(Nfs::UnescapeSpaces1 (nil)), [], nil); - TEST (``(Nfs::UnescapeSpaces1 ("")), [], nil); - TEST (``(Nfs::UnescapeSpaces1 ("\\040")), [], nil); - TEST (``(Nfs::UnescapeSpaces1 ("\\040\\040")), [], nil); - TEST (``(Nfs::UnescapeSpaces1 ("nospaces")), [], nil); - TEST (``(Nfs::UnescapeSpaces1 ("one\\040space")), [], nil); - TEST (``(Nfs::UnescapeSpaces1 ("\\040before,\\040two,\\040\\040after\\040")), [], nil); - - DUMP ("Nfs::UnescapeSpaces1 informative"); - TEST (``(Nfs::UnescapeSpaces1 ("\\041\\")), [], nil); - // see how it works when applied multiple times - TEST (``(Nfs::UnescapeSpaces1 (Nfs::UnescapeSpaces1 ("\\040"))), [], nil); -} diff --git a/testsuite/tests/nfs-options.rb b/testsuite/tests/nfs-options.rb new file mode 100644 index 0000000..eb5fa3c --- /dev/null +++ b/testsuite/tests/nfs-options.rb @@ -0,0 +1,96 @@ +# encoding: utf-8 + +module Yast + class NfsOptionsClient < Client + def main + Yast.include self, "testsuite.rb" + Yast.import "NfsOptions" + Yast.import "Assert" + + DUMP("NfsOptions::validate") + TEST(lambda { NfsOptions.validate("") }, [], nil) + TEST(lambda { NfsOptions.validate("defaults") }, [], nil) + TEST(lambda { NfsOptions.validate("nolock,bg") }, [], nil) + TEST(lambda { NfsOptions.validate("nolock,nobg") }, [], nil) + TEST(lambda { NfsOptions.validate("nolock,rsize=8192") }, [], nil) + TEST(lambda { NfsOptions.validate("nolock, bg") }, [], nil) + TEST(lambda { NfsOptions.validate("nolock,unknownoption") }, [], nil) + TEST(lambda { NfsOptions.validate("nolock,unknownassignment=true") }, [], nil) + TEST(lambda { NfsOptions.validate("nolock,rsize=") }, [], nil) + TEST(lambda { NfsOptions.validate("nolock,two=equal=signs") }, [], nil) + TEST(lambda { NfsOptions.validate("nolock,retrans=trans=trans") }, [], nil) + TEST(lambda { NfsOptions.validate("nolock,intr=bogus") }, [], nil) + + DUMP("NfsOptions::get_nfs41") + Assert.Equal(false, NfsOptions.get_nfs41("")) + Assert.Equal(false, NfsOptions.get_nfs41("defaults")) + Assert.Equal(false, NfsOptions.get_nfs41("ro,sync")) + Assert.Equal(false, NfsOptions.get_nfs41("minorversion=0")) + Assert.Equal(true, NfsOptions.get_nfs41("minorversion=1")) + # "minorversion=2" does not exist yet, YAGNI + Assert.Equal(false, NfsOptions.get_nfs41("subminorversion=1")) # substring must not match + # Assert::Equal(?, NfsOptions::get_nfs41("minorversion=1,minorversion=0")); // don't care + Assert.Equal(false, NfsOptions.get_nfs41("ro,minorversion=0,sync")) + Assert.Equal(true, NfsOptions.get_nfs41("ro,minorversion=1,sync")) + + DUMP("NfsOptions::set_nfs41") + Assert.Equal("", NfsOptions.set_nfs41("", false)) + Assert.Equal("minorversion=1", NfsOptions.set_nfs41("", true)) + + Assert.Equal("defaults", NfsOptions.set_nfs41("defaults", false)) + Assert.Equal("minorversion=1", NfsOptions.set_nfs41("defaults", true)) + + Assert.Equal("ro,sync", NfsOptions.set_nfs41("ro,sync", false)) + Assert.Equal( + "ro,sync,minorversion=1", + NfsOptions.set_nfs41("ro,sync", true) + ) + + Assert.Equal( + "minorversion=0", + NfsOptions.set_nfs41("minorversion=0", false) + ) + Assert.Equal( + "minorversion=1", + NfsOptions.set_nfs41("minorversion=0", true) + ) + + Assert.Equal("defaults", NfsOptions.set_nfs41("minorversion=1", false)) + Assert.Equal( + "minorversion=1", + NfsOptions.set_nfs41("minorversion=1", true) + ) + + Assert.Equal( + "subminorversion=1", + NfsOptions.set_nfs41("subminorversion=1", false) + ) + Assert.Equal( + "subminorversion=1,minorversion=1", + NfsOptions.set_nfs41("subminorversion=1", true) + ) + + Assert.Equal( + "ro,minorversion=0,sync", + NfsOptions.set_nfs41("ro,minorversion=0,sync", false) + ) + Assert.Equal( + "ro,sync,minorversion=1", + NfsOptions.set_nfs41("ro,minorversion=0,sync", true) + ) + + Assert.Equal( + "ro,sync", + NfsOptions.set_nfs41("ro,minorversion=1,sync", false) + ) + Assert.Equal( + "ro,minorversion=1,sync", + NfsOptions.set_nfs41("ro,minorversion=1,sync", true) + ) + + nil + end + end +end + +Yast::NfsOptionsClient.new.main diff --git a/testsuite/tests/nfs-options.ycp b/testsuite/tests/nfs-options.ycp deleted file mode 100644 index 8b48886..0000000 --- a/testsuite/tests/nfs-options.ycp +++ /dev/null @@ -1,73 +0,0 @@ -{ - include "testsuite.ycp"; - import "NfsOptions"; - import "Assert"; - - DUMP ("NfsOptions::validate"); - TEST (``(NfsOptions::validate ("")), [], nil); - TEST (``(NfsOptions::validate ("defaults")), [], nil); - TEST (``(NfsOptions::validate ("nolock,bg")), [], nil); - TEST (``(NfsOptions::validate ("nolock,nobg")), [], nil); - TEST (``(NfsOptions::validate ("nolock,rsize=8192")), [], nil); - TEST (``(NfsOptions::validate ("nolock, bg")), [], nil); - TEST (``(NfsOptions::validate ("nolock,unknownoption")), [], nil); - TEST (``(NfsOptions::validate ("nolock,unknownassignment=true")), [], nil); - TEST (``(NfsOptions::validate ("nolock,rsize=")), [], nil); - TEST (``(NfsOptions::validate ("nolock,two=equal=signs")), [], nil); - TEST (``(NfsOptions::validate ("nolock,retrans=trans=trans")), [], nil); - TEST (``(NfsOptions::validate ("nolock,intr=bogus")), [], nil); - - DUMP ("NfsOptions::get_nfs41"); - Assert::Equal(false, NfsOptions::get_nfs41("")); - Assert::Equal(false, NfsOptions::get_nfs41("defaults")); - Assert::Equal(false, NfsOptions::get_nfs41("ro,sync")); - Assert::Equal(false, NfsOptions::get_nfs41("minorversion=0")); - Assert::Equal(true, NfsOptions::get_nfs41("minorversion=1")); - // "minorversion=2" does not exist yet, YAGNI - Assert::Equal(false, NfsOptions::get_nfs41("subminorversion=1")); // substring must not match - // Assert::Equal(?, NfsOptions::get_nfs41("minorversion=1,minorversion=0")); // don't care - Assert::Equal(false, NfsOptions::get_nfs41("ro,minorversion=0,sync")); - Assert::Equal(true, NfsOptions::get_nfs41("ro,minorversion=1,sync")); - - DUMP ("NfsOptions::set_nfs41"); - Assert::Equal( "", - NfsOptions::set_nfs41("", false)); - Assert::Equal( "minorversion=1", - NfsOptions::set_nfs41("", true)); - - Assert::Equal( "defaults", - NfsOptions::set_nfs41("defaults", false)); - Assert::Equal( "minorversion=1", - NfsOptions::set_nfs41("defaults", true)); - - Assert::Equal( "ro,sync", - NfsOptions::set_nfs41("ro,sync", false)); - Assert::Equal( "ro,sync,minorversion=1", - NfsOptions::set_nfs41("ro,sync", true)); - - Assert::Equal( "minorversion=0", - NfsOptions::set_nfs41("minorversion=0", false)); - Assert::Equal( "minorversion=1", - NfsOptions::set_nfs41("minorversion=0", true)); - - Assert::Equal( "defaults", - NfsOptions::set_nfs41("minorversion=1", false)); - Assert::Equal( "minorversion=1", - NfsOptions::set_nfs41("minorversion=1", true)); - - Assert::Equal( "subminorversion=1", - NfsOptions::set_nfs41("subminorversion=1", false)); - Assert::Equal( "subminorversion=1,minorversion=1", - NfsOptions::set_nfs41("subminorversion=1", true)); - - Assert::Equal( "ro,minorversion=0,sync", - NfsOptions::set_nfs41("ro,minorversion=0,sync", false)); - Assert::Equal( "ro,sync,minorversion=1", - NfsOptions::set_nfs41("ro,minorversion=0,sync", true)); - - Assert::Equal( "ro,sync", - NfsOptions::set_nfs41("ro,minorversion=1,sync", false)); - Assert::Equal( "ro,minorversion=1,sync", - NfsOptions::set_nfs41("ro,minorversion=1,sync", true)); - -} diff --git a/testsuite/tests/r-check.rb b/testsuite/tests/r-check.rb new file mode 100644 index 0000000..c0aad51 --- /dev/null +++ b/testsuite/tests/r-check.rb @@ -0,0 +1,62 @@ +# encoding: utf-8 + +# Module: +# NFS client configuration +# +# Summary: +# Routines testuite +# +# Authors: +# Martin Vidner +# +# $Id$ +module Yast + class RCheckClient < Client + def main + # testedfiles: routines.ycp Testsuite.ycp + + Yast.include self, "testsuite.rb" + Yast.include self, "nfs/routines.rb" + + @OK_Name = "foo.bar.com.tw" + @TooLongName = "123456789012345678901234567890123456789012345678901234567890" + @IllegalName = "Something:wrong" + @IPv4 = "192.168.10.1" + @IPv4_invalid = "192.168.10:1" + @IPv6 = "fe80::219:d1ff:feac:fd10" + @IPv6_invalid = "fe80::219::fd10" + @IPv6_brackets = "[::1]" + @IPv6_brackets_invalid = "[::1" + @IPv6_link_local_nb = "fe80::3%eth0" + @IPv6_link_local_ib = "[fe80::3%eth0]" + @IPv6_link_local_invalid = "[fe80::3%]" + + DUMP("CheckHostName") + TEST(lambda { CheckHostName(@OK_Name) }, [], nil) + TEST(lambda { CheckHostName(@TooLongName) }, [], nil) + TEST(lambda { CheckHostName(@IllegalName) }, [], nil) + # Too long & illegal char + TEST(lambda { CheckHostName(Ops.add(@TooLongName, "!")) }, [], nil) + # check IPv? adresses + TEST(lambda { CheckHostName(@IPv4) }, [], nil) + TEST(lambda { CheckHostName(@IPv4_invalid) }, [], nil) + TEST(lambda { CheckHostName(@IPv6) }, [], nil) + TEST(lambda { CheckHostName(@IPv6_invalid) }, [], nil) + TEST(lambda { CheckHostName(@IPv6_brackets) }, [], nil) + TEST(lambda { CheckHostName(@IPv6_brackets_invalid) }, [], nil) + TEST(lambda { CheckHostName(@IPv6_link_local_nb) }, [], nil) + TEST(lambda { CheckHostName(@IPv6_link_local_ib) }, [], nil) + TEST(lambda { CheckHostName(@IPv6_link_local_invalid) }, [], nil) + + DUMP("FormatHostnameForFstab") + TEST(FormatHostnameForFstab("::1"), [], nil) + TEST(FormatHostnameForFstab("[::1]"), [], nil) + TEST(FormatHostnameForFstab("127.0.0.1"), [], nil) + TEST(FormatHostnameForFstab("suse.de"), [], nil) + + nil + end + end +end + +Yast::RCheckClient.new.main diff --git a/testsuite/tests/r-check.ycp b/testsuite/tests/r-check.ycp deleted file mode 100644 index fcc53c4..0000000 --- a/testsuite/tests/r-check.ycp +++ /dev/null @@ -1,54 +0,0 @@ -/** - * Module: - * NFS client configuration - * - * Summary: - * Routines testuite - * - * Authors: - * Martin Vidner - * - * $Id$ - */ -{ - // testedfiles: routines.ycp Testsuite.ycp - - include "testsuite.ycp"; - include "nfs/routines.ycp"; - - string OK_Name = "foo.bar.com.tw"; - string TooLongName = "123456789012345678901234567890123456789012345678901234567890"; - string IllegalName = "Something:wrong"; - string IPv4 = "192.168.10.1"; - string IPv4_invalid = "192.168.10:1"; - string IPv6 = "fe80::219:d1ff:feac:fd10"; - string IPv6_invalid = "fe80::219::fd10"; - string IPv6_brackets = "[::1]"; - string IPv6_brackets_invalid = "[::1"; - string IPv6_link_local_nb = "fe80::3%eth0"; - string IPv6_link_local_ib = "[fe80::3%eth0]"; - string IPv6_link_local_invalid = "[fe80::3%]"; - - DUMP ("CheckHostName"); - TEST (``(CheckHostName (OK_Name)), [], nil); - TEST (``(CheckHostName (TooLongName)), [], nil); - TEST (``(CheckHostName (IllegalName)), [], nil); - // Too long & illegal char - TEST (``(CheckHostName (TooLongName + "!")), [], nil); - // check IPv? adresses - TEST (``(CheckHostName (IPv4)), [], nil); - TEST (``(CheckHostName (IPv4_invalid)), [], nil); - TEST (``(CheckHostName (IPv6)), [], nil); - TEST (``(CheckHostName (IPv6_invalid)), [], nil); - TEST (``(CheckHostName (IPv6_brackets)), [], nil); - TEST (``(CheckHostName (IPv6_brackets_invalid)), [], nil); - TEST (``(CheckHostName (IPv6_link_local_nb)), [], nil); - TEST (``(CheckHostName (IPv6_link_local_ib)), [], nil); - TEST (``(CheckHostName (IPv6_link_local_invalid)), [], nil); - - DUMP ( "FormatHostnameForFstab"); - TEST ( FormatHostnameForFstab( "::1"), [], nil); - TEST ( FormatHostnameForFstab( "[::1]"), [], nil); - TEST ( FormatHostnameForFstab( "127.0.0.1"), [], nil); - TEST ( FormatHostnameForFstab( "suse.de"), [], nil); -} diff --git a/testsuite/tests/r-fstab.rb b/testsuite/tests/r-fstab.rb new file mode 100644 index 0000000..f9f3b59 --- /dev/null +++ b/testsuite/tests/r-fstab.rb @@ -0,0 +1,79 @@ +# encoding: utf-8 + +# Module: +# NFS client configuration +# +# Summary: +# Routines testuite +# +# Authors: +# Martin Vidner +# +# $Id$ +module Yast + class RFstabClient < Client + def main + # testedfiles: routines.ycp Testsuite.ycp + + Yast.include self, "testsuite.rb" + Yast.include self, "nfs/routines.rb" + + @PathTooLong = "12345678901234567890123456789012345678901234567890123456789012345678901234567890" + + @nfs_entries = [ + { + "file" => "/home", + "freq" => 0, + "mntops" => "defaults", + "passno" => 0, + "spec" => "foo.bar.com:/home", + "vfstype" => "nfs4" + }, + { + "file" => "/var/spool/mail", + "freq" => 0, + "mntops" => "defaults", + "passno" => 0, + "spec" => "foo.bar.com:/var/spool/mail", + "vfstype" => "nfs" + }, + { + "file" => "/install", + "freq" => 0, + "mntops" => "hard,intr", + "passno" => 0, + # different from "file" (for order tests) + "spec" => "foo.bar.com.tw:/local/install", + "vfstype" => "nfs" + } + ] + + DUMP("FstabTableItems") + TEST(lambda { FstabTableItems(@nfs_entries) }, [], nil) + + DUMP("IsMpInFstab") + # MountPoint in fstab + TEST(lambda { IsMpInFstab(@nfs_entries, "/home") }, [], nil) + # MountPoint in fstab + TEST(lambda { IsMpInFstab(@nfs_entries, "/install") }, [], nil) + # MountPoint NOT in fstab + TEST(lambda { IsMpInFstab(@nfs_entries, "/not/in/fstab") }, [], nil) + + DUMP("CheckPath") + # Empty path + TEST(lambda { CheckPath("") }, [], nil) + # Path is too long (cca 80 chars) + TEST(lambda { CheckPath(@PathTooLong) }, [], nil) + # First slash is missing + TEST(lambda { CheckPath("not/begins/with/slash") }, [], nil) + # Too long with slash + TEST(lambda { CheckPath(Ops.add("/", @PathTooLong)) }, [], nil) + # Regular path + TEST(lambda { CheckPath("/regular/path") }, [], nil) + + nil + end + end +end + +Yast::RFstabClient.new.main diff --git a/testsuite/tests/r-fstab.ycp b/testsuite/tests/r-fstab.ycp deleted file mode 100644 index ee3bc2c..0000000 --- a/testsuite/tests/r-fstab.ycp +++ /dev/null @@ -1,71 +0,0 @@ -/** - * Module: - * NFS client configuration - * - * Summary: - * Routines testuite - * - * Authors: - * Martin Vidner - * - * $Id$ - */ -{ - // testedfiles: routines.ycp Testsuite.ycp - - include "testsuite.ycp"; - include "nfs/routines.ycp"; - - string PathTooLong = "12345678901234567890123456789012345678901234567890123456789012345678901234567890"; - - list nfs_entries = [ - $[ - "file":"/home", - "freq":0, - "mntops":"defaults", - "passno":0, - "spec":"foo.bar.com:/home", - "vfstype":"nfs4" - ], - $[ - "file":"/var/spool/mail", - "freq":0, - "mntops":"defaults", - "passno":0, - "spec":"foo.bar.com:/var/spool/mail", - "vfstype":"nfs" - ], - $[ - "file":"/install", - "freq":0, - "mntops":"hard,intr", - "passno":0, - // different from "file" (for order tests) - "spec":"foo.bar.com.tw:/local/install", - "vfstype":"nfs" - ] - ]; - - DUMP ("FstabTableItems"); - TEST (``(FstabTableItems (nfs_entries)), [], nil); - - DUMP ("IsMpInFstab"); - // MountPoint in fstab - TEST (``(IsMpInFstab (nfs_entries, "/home")), [], nil); - // MountPoint in fstab - TEST (``(IsMpInFstab (nfs_entries, "/install")), [], nil); - // MountPoint NOT in fstab - TEST (``(IsMpInFstab (nfs_entries, "/not/in/fstab")), [], nil); - - DUMP ("CheckPath"); - // Empty path - TEST (``(CheckPath ("")), [], nil); - // Path is too long (cca 80 chars) - TEST (``(CheckPath (PathTooLong)), [], nil); - // First slash is missing - TEST (``(CheckPath ("not/begins/with/slash")), [], nil); - // Too long with slash - TEST (``(CheckPath ("/" + PathTooLong)), [], nil); - // Regular path - TEST (``(CheckPath ("/regular/path")), [], nil); -} diff --git a/testsuite/tests/r-spec.rb b/testsuite/tests/r-spec.rb new file mode 100644 index 0000000..88a1364 --- /dev/null +++ b/testsuite/tests/r-spec.rb @@ -0,0 +1,35 @@ +# encoding: utf-8 + +# Module: +# NFS client configuration +# +# Summary: +# Routines testuite +# +# Authors: +# Martin Vidner +# +# $Id$ +module Yast + class RSpecClient < Client + def main + # testedfiles: routines.ycp Testsuite.ycp + + Yast.include self, "testsuite.rb" + Yast.include self, "nfs/routines.rb" + + DUMP("SpecToServPath") + TEST(lambda { SpecToServPath("big.foo.com:/share/data") }, [], nil) + TEST(lambda { SpecToServPath("only.server.com:") }, [], nil) + TEST(lambda { SpecToServPath("nocolon.only.server.com") }, [], nil) + TEST(lambda { SpecToServPath(":/only/path") }, [], nil) + TEST(lambda { SpecToServPath("/nocolon/only/path") }, [], nil) + TEST(lambda { SpecToServPath("fe80::219:d1ff:feac:fd10:/path") }, [], nil) + TEST(lambda { SpecToServPath("") }, [], nil) + + nil + end + end +end + +Yast::RSpecClient.new.main diff --git a/testsuite/tests/r-spec.ycp b/testsuite/tests/r-spec.ycp deleted file mode 100644 index 1cb16c9..0000000 --- a/testsuite/tests/r-spec.ycp +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Module: - * NFS client configuration - * - * Summary: - * Routines testuite - * - * Authors: - * Martin Vidner - * - * $Id$ - */ -{ - // testedfiles: routines.ycp Testsuite.ycp - - include "testsuite.ycp"; - include "nfs/routines.ycp"; - - DUMP ("SpecToServPath"); - TEST (``(SpecToServPath ("big.foo.com:/share/data")), [], nil); - TEST (``(SpecToServPath ("only.server.com:")), [], nil); - TEST (``(SpecToServPath ("nocolon.only.server.com")), [], nil); - TEST (``(SpecToServPath (":/only/path")), [], nil); - TEST (``(SpecToServPath ("/nocolon/only/path")), [], nil); - TEST (``(SpecToServPath ("fe80::219:d1ff:feac:fd10:/path")), [], nil); - TEST (``(SpecToServPath ("")), [], nil); -} diff --git a/testsuite/tests/r-strip.rb b/testsuite/tests/r-strip.rb new file mode 100644 index 0000000..c27b612 --- /dev/null +++ b/testsuite/tests/r-strip.rb @@ -0,0 +1,32 @@ +# encoding: utf-8 + +# Module: +# NFS client configuration +# +# Summary: +# Routines testuite +# +# Authors: +# Martin Vidner +# +# $Id$ +module Yast + class RStripClient < Client + def main + # testedfiles: routines.ycp Testsuite.ycp + + Yast.include self, "testsuite.rb" + Yast.include self, "nfs/routines.rb" + + DUMP("StripExtraSlash") + TEST(lambda { StripExtraSlash("") }, [], nil) + TEST(lambda { StripExtraSlash("/") }, [], nil) + TEST(lambda { StripExtraSlash("/normal/path") }, [], nil) + TEST(lambda { StripExtraSlash("/trailing/slash/") }, [], nil) + + nil + end + end +end + +Yast::RStripClient.new.main diff --git a/testsuite/tests/r-strip.ycp b/testsuite/tests/r-strip.ycp deleted file mode 100644 index a206acc..0000000 --- a/testsuite/tests/r-strip.ycp +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Module: - * NFS client configuration - * - * Summary: - * Routines testuite - * - * Authors: - * Martin Vidner - * - * $Id$ - */ -{ - // testedfiles: routines.ycp Testsuite.ycp - - include "testsuite.ycp"; - include "nfs/routines.ycp"; - - DUMP ("StripExtraSlash"); - TEST (``(StripExtraSlash ("")), [], nil); - TEST (``(StripExtraSlash ("/")), [], nil); - TEST (``(StripExtraSlash ("/normal/path")), [], nil); - TEST (``(StripExtraSlash ("/trailing/slash/")), [], nil); -} diff --git a/testsuite/tests/readwrite.rb b/testsuite/tests/readwrite.rb new file mode 100644 index 0000000..09065a2 --- /dev/null +++ b/testsuite/tests/readwrite.rb @@ -0,0 +1,133 @@ +# encoding: utf-8 + +# Module: +# NFS client configuration +# +# Summary: +# Testsuite +# +# Authors: +# Martin Vidner +# +# $Id$ +module Yast + class ReadwriteClient < Client + def main + # testedfiles: Nfs.ycp Service.ycp Report.ycp Testsuite.ycp + + Yast.include self, "testsuite.rb" + + @I_READ = { "target" => { "size" => 0 } } + @I_WRITE = {} + @I_EXEC = { "target" => { "bash_output" => {} } } + TESTSUITE_INIT([@I_READ, @I_WRITE, @I_EXEC], nil) + + Yast.import "Nfs" + Yast.import "Report" + Yast.import "Progress" + + @progress_orig = Progress.set(false) + Report.DisplayErrors(false, 0) + + @service_on = { "start" => ["3", "5"], "stop" => ["3", "5"] } + @service_off = { "start" => [], "stop" => [] } + @READ = { + # Runlevel: + "init" => { + "scripts" => { + "exists" => true, + "runlevel" => { + "portmap" => @service_on, + "nfs" => @service_on, + "nfsboot" => @service_off, + "network" => @service_off, + "networkmanager" => @service_on + }, + # their contents is not important for ServiceAdjust + "comment" => { + "portmap" => {}, + "nfs" => {} + } + } + }, + # // targetpkg: + # "targetpkg": $[ + # // autofs + # "installed": true, + # ], + # Nis itself: + "etc" => { + "fstab" => [ + { + "file" => "/", + "freq" => 1, + "mntops" => "defaults", + "passno" => 2, + "spec" => "/dev/hda6", + "vfstype" => "reiserfs" + }, + { + "file" => "/home", + "freq" => 0, + "mntops" => "defaults", + "passno" => 0, + "spec" => "foo.bar.com:/home", + "vfstype" => "nfs" + }, + { + "file" => "/var/spool/mail", + "freq" => 0, + "mntops" => "defaults", + "passno" => 0, + "spec" => "foo.bar.com:/var/spool/mail", + "vfstype" => "nfs" + }, + { + "file" => "/a\\040space", + "freq" => 1, + "mntops" => "defaults", + "passno" => 3, + "spec" => "/dev/hda7", + "vfstype" => "reiserfs" + }, + { + "file" => "/b\\040space", + "freq" => 0, + "mntops" => "defaults", + "passno" => 0, + "spec" => "foo.bar.com:/space\\040dir", + "vfstype" => "nfs" + } + ], + "idmapd_conf" => "localhost" + }, + "sysconfig" => { + "nfs" => { "NFS4_SUPPORT" => "yes", "NFS_SECURITY_GSS" => "yes" } + }, + "target" => { "stat" => { "dummy" => true } } + } + + @WRITE = {} + + @WRITE_KO = { "etc" => { "fstab" => false } } + + @EXECUTE = { + "target" => { + "bash_output" => { "exit" => 0, "stdout" => "", "stderr" => "" }, + "mkdir" => true + } + } + + DUMP("Read") + TEST(lambda { Nfs.Read }, [@READ, @WRITE, @EXECUTE], nil) + DUMP("Write OK") + TEST(lambda { Nfs.Write }, [@READ, @WRITE, @EXECUTE], nil) + DUMP("Write KO") + TEST(lambda { Nfs.Write }, [@READ, @WRITE_KO, @EXECUTE], nil) + + nil + end + end +end + +Yast::ReadwriteClient.new.main diff --git a/testsuite/tests/readwrite.ycp b/testsuite/tests/readwrite.ycp deleted file mode 100644 index 835437f..0000000 --- a/testsuite/tests/readwrite.ycp +++ /dev/null @@ -1,155 +0,0 @@ -/** - * Module: - * NFS client configuration - * - * Summary: - * Testsuite - * - * Authors: - * Martin Vidner - * - * $Id$ - */ -{ - // testedfiles: Nfs.ycp Service.ycp Report.ycp Testsuite.ycp - - include "testsuite.ycp"; - - map I_READ = $[ - "target" : $[ - "size" : 0, - ], - ]; - map I_WRITE = $[]; - map I_EXEC = $[ - "target" : $[ - "bash_output" : $[], - ], - ]; - TESTSUITE_INIT ([I_READ, I_WRITE, I_EXEC], nil); - - import "Nfs"; - import "Report"; - import "Progress"; - - boolean progress_orig = Progress::set (false); - Report::DisplayErrors (false, 0); - - map service_on = $[ - "start": [ "3", "5"], - "stop": [ "3", "5"], - ]; - map service_off = $[ - "start": [], - "stop": [], - ]; - map READ = $[ - // Runlevel: - "init": $[ - "scripts": $[ - "exists": true, - "runlevel": $[ - "portmap": service_on, - "nfs": service_on, - "nfsboot": service_off, - "network": service_off, - "networkmanager": service_on, - ], - // their contents is not important for ServiceAdjust - "comment": $[ - "portmap": $[], - "nfs": $[], - ], - ], - ], - /* - // targetpkg: - "targetpkg": $[ - // autofs - "installed": true, - ], - */ - // Nis itself: - "etc": $[ - "fstab": [ - $[ - "file":"/", - "freq":1, - "mntops":"defaults", - "passno":2, - "spec":"/dev/hda6", - "vfstype":"reiserfs" - ], - $[ - "file":"/home", - "freq":0, - "mntops":"defaults", - "passno":0, - "spec":"foo.bar.com:/home", - "vfstype":"nfs", - ], - $[ - "file":"/var/spool/mail", - "freq":0, - "mntops":"defaults", - "passno":0, - "spec":"foo.bar.com:/var/spool/mail", - "vfstype":"nfs", - ], - $[ - "file":"/a\\040space", - "freq":1, - "mntops":"defaults", - "passno":3, - "spec":"/dev/hda7", - "vfstype":"reiserfs" - ], - $[ - "file":"/b\\040space", - "freq":0, - "mntops":"defaults", - "passno":0, - "spec":"foo.bar.com:/space\\040dir", - "vfstype":"nfs", - ], - ], - "idmapd_conf" : "localhost" - ], - "sysconfig": $[ - "nfs" : $[ - "NFS4_SUPPORT": "yes", - "NFS_SECURITY_GSS": "yes", - ], - ], - "target" : $[ - "stat" : $[ "dummy": true ] - ], - ]; - - map WRITE = $[ - ]; - - map WRITE_KO = $[ - "etc": $[ - "fstab": false, - ], - ]; - - map EXECUTE = $[ - "target": $[ - "bash_output": $[ - "exit": 0, - "stdout": "", - "stderr": "", - ], - "mkdir": true, - ], - ]; - - DUMP ("Read"); - TEST (``(Nfs::Read ()), [READ, WRITE, EXECUTE], nil); - DUMP ("Write OK"); - TEST (``(Nfs::Write ()), [READ, WRITE, EXECUTE], nil); - DUMP ("Write KO"); - TEST (``(Nfs::Write ()), [READ, WRITE_KO, EXECUTE], nil); -} diff --git a/testsuite/tests/readwrite2.rb b/testsuite/tests/readwrite2.rb new file mode 100644 index 0000000..82106ba --- /dev/null +++ b/testsuite/tests/readwrite2.rb @@ -0,0 +1,222 @@ +# encoding: utf-8 + +# Module: +# NFS client configuration +# +# Summary: +# Testsuite +# +# Authors: +# Martin Vidner +# +# $Id$ +module Yast + class Readwrite2Client < Client + def main + # testedfiles: Nfs.ycp Service.ycp Report.ycp Testsuite.ycp + + Yast.include self, "testsuite.rb" + + @I_READ = { "target" => { "size" => 0 } } + @I_WRITE = {} + @I_EXEC = { "target" => { "bash_output" => {} } } + TESTSUITE_INIT([@I_READ, @I_WRITE, @I_EXEC], nil) + + Yast.import "Nfs" + Yast.import "Report" + Yast.import "Progress" + + @progress_orig = Progress.set(false) + Report.DisplayErrors(false, 0) + + @service_on = { "start" => ["3", "5"], "stop" => ["3", "5"] } + @service_off = { "start" => [], "stop" => [] } + @READ = { + # Runlevel: + "init" => { + "scripts" => { + "exists" => true, + "runlevel" => { "portmap" => @service_on, "nfs" => @service_on }, + # their contents is not important for ServiceAdjust + "comment" => { + "portmap" => {}, + "nfs" => {} + } + } + }, + # Nis itself: + "etc" => { + "fstab" => [ + { + "file" => "/", + "freq" => 1, + "mntops" => "defaults", + "passno" => 2, + "spec" => "/dev/hda6", + "vfstype" => "reiserfs" + }, + { + "file" => "/home", + "freq" => 0, + "mntops" => "defaults", + "passno" => 0, + "spec" => "foo.bar.com:/home", + "vfstype" => "nfs" + }, + { + "file" => "/var/spool/mail", + "freq" => 0, + "mntops" => "defaults", + "passno" => 0, + "spec" => "foo.bar.com:/var/spool/mail", + "vfstype" => "nfs" + }, + { + "file" => "/a\\040space", + "freq" => 1, + "mntops" => "defaults", + "passno" => 3, + "spec" => "/dev/hda7", + "vfstype" => "reiserfs" + }, + { + "file" => "/b\\040space", + "freq" => 0, + "mntops" => "defaults", + "passno" => 0, + "spec" => "foo.bar.com:/space\\040dir", + "vfstype" => "nfs" + } + ], + "idmapd_conf" => "localhost" + }, + "sysconfig" => { + "nfs" => { "NFS4_SUPPORT" => "no", "NFS_SECURITY_GSS" => "no" } + }, + "target" => { "stat" => { "dummy" => true } } + } + + # services portmap & nfs are stopped. + @READ3 = Builtins.eval(@READ) + Ops.set(@READ3, ["init", "scripts", "runlevel", "portmap"], @service_off) + Ops.set(@READ3, ["init", "scripts", "runlevel", "nfs"], @service_off) + + # no nfs file-systems in /etc/fstab + @EMPTY = Builtins.eval(@READ) + Ops.set( + @EMPTY, + ["etc", "fstab"], + [ + { + "file" => "/", + "freq" => 1, + "mntops" => "defaults", + "passno" => 2, + "spec" => "/dev/hda6", + "vfstype" => "ext3" + } + ] + ) + + # services portmap & nfs are stopped; and /etc/fstab contains no nfs imports + @EMPTY3 = Builtins.eval(@READ3) + Ops.set( + @EMPTY3, + ["etc", "fstab"], + [ + { + "file" => "/", + "freq" => 1, + "mntops" => "defaults", + "passno" => 2, + "spec" => "/dev/hda6", + "vfstype" => "ext3" + } + ] + ) + + @WRITE = {} + + @WRITE_KO = { "etc" => { "fstab" => false } } + + @EXECUTE = { + "target" => { + "bash_output" => { "exit" => 0, "stdout" => "", "stderr" => "" }, + "mkdir" => true + } + } + + # fstab contains nfs mounts & services are running + DUMP("\nRead - nfs is in use & running\n") + TEST(lambda { Nfs.Read }, [@READ, @WRITE, @EXECUTE], nil) + # fstab unchanged + DUMP("\nWrite - nfs is in use - start services\n") + TEST(lambda { Nfs.Write }, [@READ, @WRITE, @EXECUTE], nil) + + # fstab contains nfs mounts & services are stopped:-( + DUMP("\nRead - nfs is in use & stopped\n") + TEST(lambda { Nfs.Read }, [@READ3, @WRITE, @EXECUTE], nil) + # fstab unchanged - so, start services + DUMP("\nWrite - nfs is in use - so, start services\n") + TEST(lambda { Nfs.Write }, [@READ3, @WRITE, @EXECUTE], nil) + + # fstab contains no nfs mounts, services are running + DUMP("\nRead - nfs not used & running\n") + TEST(lambda { Nfs.Read }, [@EMPTY, @WRITE, @EXECUTE], nil) + # fstab unchanged - so, STOP services + DUMP("\nWrite - nfs not used - so, stopping services\n") + TEST(lambda { Nfs.Write }, [@EMPTY, @WRITE, @EXECUTE], nil) + + # fstab contains no nfs mount, serives are stopped + DUMP("\nRead - nfs not used & services are stopped\n") + TEST(lambda { Nfs.Read }, [@EMPTY3, @WRITE, @EXECUTE], nil) + # fstab unchanged - so, leave services stopped + DUMP("\nWrite - nfs not used; leave services stopped\n") + TEST(lambda { Nfs.Write }, [@EMPTY3, @WRITE, @EXECUTE], nil) + + # // nfs and portmap are running + # DUMP ("\nRead - services are running\n"); + # TEST (``(Nfs::Read ()), [READ, WRITE, EXECUTE], nil); + # DUMP ("\nWrite - services will be stopped\n"); + # // Stop services! + # // Nfs::start = false; + # // And Write + # TEST (``(Nfs::Write ()), [READ, WRITE, EXECUTE], nil); + # + # // nfs and portmap are running + # DUMP ("\nRead - services are running\n"); + # TEST (``(Nfs::Read ()), [READ, WRITE, EXECUTE], nil); + # DUMP ("\nWrite - services are running\n"); + # // Start services (nfsserver) + # // Nfs::start = true; + # // And Write + # TEST (``(Nfs::Write ()), [READ, WRITE, EXECUTE], nil); + # + # // nfs and portmap are stopped + # DUMP ("\nRead - services are stopped\n"); + # TEST (``(Nfs::Read ()), [READ3, WRITE, EXECUTE], nil); + # DUMP ("\nWrite - services will be stopped\n"); + # // Leave services stopped + # // Nfs::start = false; + # // And Write + # TEST (``(Nfs::Write ()), [READ3, WRITE, EXECUTE], nil); + # + # // nfs and portmap are stopped + # DUMP ("\nRead - services are stopped\n"); + # TEST (``(Nfs::Read ()), [READ3, WRITE, EXECUTE], nil); + # DUMP ("\nWrite - services will be started\n"); + # // Start services + # // Nfs::start = true; + # // And Write + # TEST (``(Nfs::Write ()), [READ3, WRITE, EXECUTE], nil); + # + # DUMP ("\nEMPTY\n"); + # TEST (``(Nfs::Read ()), [EMPTY, WRITE, EXECUTE], nil); + # TEST (``(Nfs::Write ()), [EMPTY, WRITE, EXECUTE], nil); + + nil + end + end +end + +Yast::Readwrite2Client.new.main diff --git a/testsuite/tests/readwrite2.ycp b/testsuite/tests/readwrite2.ycp deleted file mode 100644 index 38ba536..0000000 --- a/testsuite/tests/readwrite2.ycp +++ /dev/null @@ -1,237 +0,0 @@ -/** - * Module: - * NFS client configuration - * - * Summary: - * Testsuite - * - * Authors: - * Martin Vidner - * - * $Id$ - */ -{ - // testedfiles: Nfs.ycp Service.ycp Report.ycp Testsuite.ycp - - include "testsuite.ycp"; - - map I_READ = $[ - "target" : $[ - "size" : 0, - ], - ]; - map I_WRITE = $[]; - map I_EXEC = $[ - "target" : $[ - "bash_output" : $[], - ], - ]; - TESTSUITE_INIT ([I_READ, I_WRITE, I_EXEC], nil); - - import "Nfs"; - import "Report"; - import "Progress"; - - boolean progress_orig = Progress::set (false); - Report::DisplayErrors (false, 0); - - map service_on = $[ - "start": [ "3", "5"], - "stop": [ "3", "5"], - ]; - map service_off = $[ - "start": [], - "stop": [], - ]; - map READ = $[ - // Runlevel: - "init": $[ - "scripts": $[ - "exists": true, - "runlevel": $[ - "portmap": service_on, - "nfs": service_on, - ], - // their contents is not important for ServiceAdjust - "comment": $[ - "portmap": $[], - "nfs": $[], - ], - ], - ], - // Nis itself: - "etc": $[ - "fstab": [ - $[ - "file":"/", - "freq":1, - "mntops":"defaults", - "passno":2, - "spec":"/dev/hda6", - "vfstype":"reiserfs", - ], - $[ - "file":"/home", - "freq":0, - "mntops":"defaults", - "passno":0, - "spec":"foo.bar.com:/home", - "vfstype":"nfs", - ], - $[ - "file":"/var/spool/mail", - "freq":0, - "mntops":"defaults", - "passno":0, - "spec":"foo.bar.com:/var/spool/mail", - "vfstype":"nfs", - ], - $[ - "file":"/a\\040space", - "freq":1, - "mntops":"defaults", - "passno":3, - "spec":"/dev/hda7", - "vfstype":"reiserfs", - ], - $[ - "file":"/b\\040space", - "freq":0, - "mntops":"defaults", - "passno":0, - "spec":"foo.bar.com:/space\\040dir", - "vfstype":"nfs", - ], - ], - "idmapd_conf" : "localhost" - ], - "sysconfig": $[ - "nfs" : $[ - "NFS4_SUPPORT": "no", - "NFS_SECURITY_GSS": "no", - ], - ], - "target" : $[ - "stat" : $[ "dummy": true ] - ], - ]; - - // services portmap & nfs are stopped. - map READ3 = (map) eval (READ); - READ3["init","scripts","runlevel","portmap"] = service_off; - READ3["init","scripts","runlevel","nfs"] = service_off; - - // no nfs file-systems in /etc/fstab - map EMPTY = (map) eval (READ); - EMPTY["etc","fstab"] = [ - $[ - "file":"/", - "freq":1, - "mntops":"defaults", - "passno":2, - "spec":"/dev/hda6", - "vfstype":"ext3", - ], - ]; - - // services portmap & nfs are stopped; and /etc/fstab contains no nfs imports - map EMPTY3 = (map) eval (READ3); - EMPTY3["etc","fstab"] = [ - $[ - "file":"/", - "freq":1, - "mntops":"defaults", - "passno":2, - "spec":"/dev/hda6", - "vfstype":"ext3", - ], - ]; - - map WRITE = $[ - ]; - - map WRITE_KO = $[ - "etc": $[ - "fstab": false, - ], - ]; - - map EXECUTE = $[ - "target": $[ - "bash_output": $[ - "exit": 0, - "stdout": "", - "stderr": "", - ], - "mkdir": true, - ], - ]; - - // fstab contains nfs mounts & services are running - DUMP ("\nRead - nfs is in use & running\n"); - TEST (``(Nfs::Read ()), [READ, WRITE, EXECUTE], nil); - // fstab unchanged - DUMP ("\nWrite - nfs is in use - start services\n"); - TEST (``(Nfs::Write ()), [READ, WRITE, EXECUTE], nil); - - // fstab contains nfs mounts & services are stopped:-( - DUMP ("\nRead - nfs is in use & stopped\n"); - TEST (``(Nfs::Read ()), [READ3, WRITE, EXECUTE], nil); - // fstab unchanged - so, start services - DUMP ("\nWrite - nfs is in use - so, start services\n"); - TEST (``(Nfs::Write ()), [READ3, WRITE, EXECUTE], nil); - - // fstab contains no nfs mounts, services are running - DUMP ("\nRead - nfs not used & running\n"); - TEST (``(Nfs::Read ()), [EMPTY, WRITE, EXECUTE], nil); - // fstab unchanged - so, STOP services - DUMP ("\nWrite - nfs not used - so, stopping services\n"); - TEST (``(Nfs::Write ()), [EMPTY, WRITE, EXECUTE], nil); - - // fstab contains no nfs mount, serives are stopped - DUMP ("\nRead - nfs not used & services are stopped\n"); - TEST (``(Nfs::Read ()), [EMPTY3, WRITE, EXECUTE], nil); - // fstab unchanged - so, leave services stopped - DUMP ("\nWrite - nfs not used; leave services stopped\n"); - TEST (``(Nfs::Write ()), [EMPTY3, WRITE, EXECUTE], nil); - -/* // nfs and portmap are running - DUMP ("\nRead - services are running\n"); - TEST (``(Nfs::Read ()), [READ, WRITE, EXECUTE], nil); - DUMP ("\nWrite - services will be stopped\n"); - // Stop services! -// Nfs::start = false; - // And Write - TEST (``(Nfs::Write ()), [READ, WRITE, EXECUTE], nil); - - // nfs and portmap are running - DUMP ("\nRead - services are running\n"); - TEST (``(Nfs::Read ()), [READ, WRITE, EXECUTE], nil); - DUMP ("\nWrite - services are running\n"); - // Start services (nfsserver) -// Nfs::start = true; - // And Write - TEST (``(Nfs::Write ()), [READ, WRITE, EXECUTE], nil); - - // nfs and portmap are stopped - DUMP ("\nRead - services are stopped\n"); - TEST (``(Nfs::Read ()), [READ3, WRITE, EXECUTE], nil); - DUMP ("\nWrite - services will be stopped\n"); - // Leave services stopped -// Nfs::start = false; - // And Write - TEST (``(Nfs::Write ()), [READ3, WRITE, EXECUTE], nil); - - // nfs and portmap are stopped - DUMP ("\nRead - services are stopped\n"); - TEST (``(Nfs::Read ()), [READ3, WRITE, EXECUTE], nil); - DUMP ("\nWrite - services will be started\n"); - // Start services -// Nfs::start = true; - // And Write - TEST (``(Nfs::Write ()), [READ3, WRITE, EXECUTE], nil); - - DUMP ("\nEMPTY\n"); - TEST (``(Nfs::Read ()), [EMPTY, WRITE, EXECUTE], nil); - TEST (``(Nfs::Write ()), [EMPTY, WRITE, EXECUTE], nil);*/ -} From 4e7567805a9544ab5bf23bfee6db144e5cfae26d Mon Sep 17 00:00:00 2001 From: Martin Vidner Date: Fri, 13 Sep 2013 13:50:13 +0200 Subject: [PATCH 50/50] yk makefile --- src/Makefile.am | 55 +++++++++++++++++++------------------------------ 1 file changed, 21 insertions(+), 34 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 380f1a3..3b94f20 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,41 +1,28 @@ -# Makefile.am for source/nfs-client/src +# Sources for nfs-client -myincludedir = @yncludedir@/nfs +module_DATA = \ + modules/Nfs.rb \ + modules/NfsOptions.rb -YCPC_Y2DIR = . +client_DATA = \ + clients/nfs_auto.rb \ + clients/nfs-client4part.rb \ + clients/nfs-client.rb \ + clients/nfs.rb -client_DATA = \ - clients/nfs_auto.ycp \ - clients/nfs-client.ycp \ - clients/nfs-client4part.ycp \ - clients/nfs.ycp +yncludedir = @yncludedir@/nfs +ynclude_DATA = \ + include/nfs/routines.rb \ + include/nfs/ui.rb \ + include/nfs/wizards.rb -myinclude_DATA = \ - include/nfs/routines.ycp \ - include/nfs/ui.ycp \ - include/nfs/wizards.ycp +schemafilesdir = $(schemadir)/autoyast/rnc +schemafiles_DATA = \ + autoyast-rnc/nfs.rnc -module_DATA = \ - modules/NfsOptions.ycp \ - modules/Nfs.ycp +desktop_DATA = \ + desktop/nfs.desktop -desktop_DATA = nfs.desktop +EXTRA_DIST = $(module_DATA) $(client_DATA) $(ynclude_DATA) $(schemafiles_DATA) $(desktop_DATA) -rncdir = $(schemadir)/autoyast/rnc -rnc_DATA = nfs.rnc - -nfs_client_version_checked = 1.2.7 -nfs_client_version_installed := $(shell rpm --queryformat %{Version} -q nfs-client) - -version-check: - @if test "$(nfs_client_version_checked)" \< "$(nfs_client_version_installed)"; then \ - echo -e "\nWARNING: List of nfs-client options might be obsolete."; \ - echo "Checked version: $(nfs_client_version_checked)"; \ - echo -e "Used version: $(nfs_client_version_installed)\n"; \ - fi; - -check-local: version-check - -EXTRA_DIST = $(client_DATA) $(myinclude_DATA) $(module_DATA) $(nfs_module_DATA) $(desktop_DATA) $(rnc_DATA) - -include $(top_srcdir)/Makefile.am.common +include $(top_srcdir)/Makefile.am.common \ No newline at end of file