From ccde9a1ce52c4125394f60d959c87d74b607a053 Mon Sep 17 00:00:00 2001 From: Martin Vidner Date: Fri, 13 Sep 2013 13:50:27 +0200 Subject: [PATCH] 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);*/ -}