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

  1. /**
  2.  * File:    modules/IscsiClient.ycp
  3.  * Package:    Configuration of iscsi-client
  4.  * Summary:    IscsiClient settings, input and output functions
  5.  * Authors:    Michal Zugec <mzugec@suse.cz>
  6.  *
  7.  * $Id: IscsiClient.ycp 31393 2006-06-08 13:37:10Z mzugec $
  8.  *
  9.  * Representation of the configuration of iscsi-client.
  10.  * Input and output routines.
  11.  */
  12.  
  13. {
  14.  
  15. module "IscsiClient";
  16. textdomain "iscsi-client";
  17.  
  18. import "Progress";
  19. import "Report";
  20. import "Summary";
  21. import "Message";
  22. import "Service";
  23. import "Package";
  24. import "Popup";
  25. import "Stage";
  26. import "Confirm";
  27.  
  28. global list <string> sessions = [];
  29. global list <string> discovered = [];
  30. global list <string> targets = [];
  31. boolean serviceStatus = false;
  32. map<string, any> config = $[];
  33.  
  34. // get accessor for service status
  35. global boolean GetStartService() {
  36.  boolean status = Service::Enabled("open-iscsi");
  37.  y2milestone("Status of open-iscsi %1", status);
  38.  return status;
  39. }
  40.  
  41. // set accessor for service status
  42. global void SetStartService(boolean status) {
  43.  y2milestone("Set status of open-iscsi to %1", status);
  44.  if (status == true) Service::Enable("open-iscsi");
  45.         else Service::Disable("open-iscsi");
  46. }
  47.  
  48.  
  49. // read configuration file
  50. global list <map<string, any> > getConfig(){
  51.  config = (map<string, any>) SCR::Read(.etc.iscsid.all);
  52.  y2milestone("read config %1", config);
  53.  return config["value"]:[];
  54. }
  55.  
  56. // write temporary changed old config
  57. global void oldConfig(){
  58.  y2milestone("Store temporary config");
  59.  SCR::Write(.etc.iscsid.all, config);
  60. }
  61.  
  62.  
  63. global map<string, any> getNode(string rec){
  64.   map<string, any> cmd = (map<string, any>)SCR::Execute(.target.bash_output, "iscsiadm -S -m node -r $REC", $["REC":rec]);
  65. //  y2internal("getting record ... %1", cmd);
  66.  if (cmd["exit"]:0!=0) return $[];
  67.  map<string, any> auth = $[];
  68.  foreach(string row, splitstring(cmd["stdout"]:"", "\n"), {
  69.  string key = splitstring(row," = ")[0]:"";
  70.  string val = splitstring(row," = ")[3]:"";
  71.  if(val == "<empty>") val="";
  72.   switch(key){
  73.    case("node.session.auth.authmethod"):
  74.         auth["authmethod"]=val;
  75.         break;
  76.    case("node.session.auth.username"):
  77.         auth["username"]=val;
  78.         break;
  79.    case("node.session.auth.password"):
  80.         auth["password"]=val;
  81.         break;
  82.    case("node.session.auth.username_in"):
  83.         auth["username_in"]=val;
  84.         break;
  85.    case("node.session.auth.password_in"):
  86.         auth["password_in"]=val;
  87.         break;
  88.   }
  89.  });
  90. // y2internal("%1", auth);
  91.  return auth;
  92. }
  93.  
  94. // create map from given map in format needed by ini-agent
  95. map<string, any> createMap(map<string, any> old_map, list<string> comments)
  96. {
  97.  string comment = "";
  98.  foreach(string row, comments, {
  99.   comment = sformat("%1%2", comment, row);
  100.   });
  101.  return $[ "name":old_map["KEY"]:"",
  102.            "value":old_map["VALUE"]:"",
  103.            "kind":"value",
  104.            "type":1,
  105.            "comment":comment
  106.          ];
  107. }
  108.  
  109. // add or modify given map
  110. list <map<string, any> > setOrAdd(list <map<string, any> > old_list, string key, string value){
  111.  list <map<string, any> > new_list = [];
  112.  boolean found = false;
  113.  foreach(map<string, any> row, old_list, {
  114.   if (row["name"]:"" == key){
  115.    found = true;
  116.    row["value"] = value;
  117.   }
  118.   new_list = add(new_list, row);
  119.  });
  120.  if (!found) new_list = add(new_list, createMap($["KEY":key, "VALUE":value], []) );
  121.  return new_list;
  122. }
  123.  
  124. // delete record with given key
  125. list <map<string, any> > delete(list <map<string, any> > old_list, string key){
  126.  y2milestone("Delete record for %1", key);
  127.  list <map<string, any> > new_list = [];
  128.  foreach(map<string, any> row, old_list, {
  129.   if (row["name"]:"" != key) new_list = add(new_list, row);
  130.  });
  131.  return new_list;
  132. }
  133.  
  134. // temporary change config for discovery authentication
  135. global void saveConfig(string user_in, string pass_in, string user_out, string pass_out){
  136.  y2milestone("Save config");
  137.  map<string, any> tmp_conf = config;
  138.  list <map<string, any> > tmp_val = tmp_conf["value"]:[];
  139.  
  140.  if ((size(user_in)>0)&&(size(pass_in)>0)) {
  141.     tmp_val = setOrAdd(tmp_val, "node.session.auth.username", user_in);
  142.     tmp_val = setOrAdd(tmp_val, "node.session.auth.password", pass_in);
  143.     }
  144.   else {
  145.     tmp_val = delete(tmp_val, "node.session.auth.username");
  146.     tmp_val = delete(tmp_val, "node.session.auth.password");
  147.     }
  148.  
  149.  if ((size(user_out)>0)&&(size(pass_out)>0)) {
  150.     tmp_val = setOrAdd(tmp_val, "discovery.sendtargets.auth.authmethod", "CHAP");
  151.     tmp_val = setOrAdd(tmp_val, "discovery.sendtargets.auth.username", user_out);
  152.     tmp_val = setOrAdd(tmp_val, "discovery.sendtargets.auth.password", pass_out);
  153.     }
  154.   else {
  155.     tmp_val = delete(tmp_val, "discovery.sendtargets.auth.authmethod");
  156.     tmp_val = delete(tmp_val, "discovery.sendtargets.auth.username");
  157.     tmp_val = delete(tmp_val, "discovery.sendtargets.auth.password");
  158.     }
  159.  tmp_conf["value"] = tmp_val;
  160.  SCR::Write(.etc.iscsid.all, tmp_conf);
  161.  SCR::Write(.etc.iscsid, nil);
  162. }
  163.  
  164. /**
  165.  * Prototypes
  166.  */
  167. global boolean Modified();
  168.  
  169. /**
  170.  * Data was modified?
  171.  */
  172. global boolean modified = false;
  173.  
  174. /**
  175.  */
  176. global boolean proposal_valid = false;
  177.  
  178. /**
  179.  * Write only, used during autoinstallation.
  180.  * Don't run services and SuSEconfig, it's all done at one place.
  181.  */
  182. global boolean write_only = false;
  183.  
  184. /**
  185.  * Abort function
  186.  * return boolean return true if abort
  187.  */
  188. global boolean() AbortFunction = Modified;
  189.  
  190. /**
  191.  * Abort function
  192.  * @return boolean return true if abort
  193.  */
  194. global define boolean Abort() ``{
  195.     if(AbortFunction != nil)
  196.     {
  197.     return AbortFunction () == true;
  198.     }
  199.     return false;
  200. }
  201.  
  202. /**
  203.  * Data was modified?
  204.  * @return true if modified
  205.  */
  206. global boolean Modified() {
  207.     y2debug("modified=%1",modified);
  208.     return modified;
  209. }
  210.  
  211. // get all discovered targets
  212. global list<string> getDiscovered(){
  213.     map<string, any> retcode = (map<string, any>)SCR::Execute(.target.bash_output, "iscsiadm -m node");
  214.     if (size(retcode["stderr"]:"")>0) {
  215.      discovered=[];
  216.     } else
  217.           discovered = filter(string row, splitstring(retcode["stdout"]:"", "\n"), {
  218.                         return ( size(row)>0 && (search(row, "session")==nil) );
  219.                         });
  220.  y2milestone("Discovered sessions %1", discovered);
  221.  return discovered;
  222. }
  223.  
  224. // get all connected targets
  225. global boolean readSessions(){
  226.  y2milestone("reading current settings");
  227.     map<string, any> retcode = (map<string, any>)SCR::Execute(.target.bash_output, "iscsiadm -m session");
  228.     if (size(retcode["stderr"]:"")>0) return false;
  229. //y2internal("retcode %1", retcode);
  230.       sessions = filter(string row, splitstring(retcode["stdout"]:"", "\n"), {
  231.                         return ( size(row)>0 && (search(row, "session")==nil) );
  232.                         });
  233.   y2milestone("Return list from iscsiadm -m session: %1", sessions);
  234.  return true;
  235. }
  236.  
  237. // check initiatorname if exist, if no - create it
  238. global boolean checkInitiatorName(){
  239.  boolean ret=true;
  240.  string file="/etc/initiatorname.iscsi";
  241.  y2milestone("Check %1", file);
  242.  if (size((map<string, any>)SCR::Read (.target.lstat, file)) == 0){
  243.  y2milestone("%1 not exist, create", file);
  244.  map<string, any> output = (map<string, any>)SCR::Execute (.target.bash_output,
  245.                                 "/sbin/iscsi-iname -p iqn.`date +%Y-%m`.de.suse:01", $[]);
  246.  if (size(output["stderr"]:"")==0){
  247.   ret = (boolean)SCR::Write (.target.string, file, sformat("InitiatorName=%1", output["stdout"]:""));
  248.     SCR::Execute (.target.bash, "chmod 0600 $FILE" ,$["FILE":file]);
  249.   } else ret = false;
  250.  }
  251.  return ret;
  252. }
  253.  
  254. // check if package open-iscsi is installed
  255. boolean installed_packages(){
  256.  y2milestone("Check if open-iscsi package installed");
  257.  boolean ret = false;
  258.   if( !Package::InstallMsg( "open-iscsi",
  259.             _("<p>To configure the iSCSI initiator, the <b>%1</b> package must be installed.</p>") +
  260.             _("<p>Install it now?</p>")) )
  261.         {
  262.         Popup::Error( Message::CannotContinueWithoutPackagesInstalled() );
  263.     } else ret = true;
  264.  return ret;
  265. }
  266.  
  267. // delete deiscovered target from database
  268. global boolean deleteRecord(string record){
  269.  boolean ret = true;
  270.  y2milestone("Delete record %1", record);
  271.  
  272.     map<string, any> retcode = (map<string, any>)SCR::Execute(.target.bash_output, sformat("iscsiadm -m node -r %1 --logout", record));
  273.         if (size(retcode["stderr"]:"")>0) return false;
  274.  
  275.  readSessions();
  276.  return ret;
  277. }
  278.  
  279. // get (manual/automatic) status of target connecting
  280. global string getStartupStatus(string record){
  281.  string status = "";
  282.  y2milestone("Getting status of record %1", record);
  283.      map<string, any> retcode = (map<string, any>)SCR::Execute(.target.bash_output, sformat("iscsiadm -m node -r %1 ", record));
  284.     if (size(retcode["stderr"]:"")>0) return "";
  285.     foreach(string row, splitstring(retcode["stdout"]:"", "\n"), {
  286.      if (issubstring(row, "node.conn[0].startup")){
  287.     status = (splitstring(row, " "))[2]:"";
  288.        break;
  289.       }
  290.     });
  291.  y2milestone("Startup status for %1 is %2", record, status);
  292.  return status;
  293. }
  294.  
  295. // update authentication value
  296. global boolean setValue(string record, string name, string value){
  297.  y2milestone("set %1  for record %3", name, record);
  298.  string command = sformat("iscsiadm -m node -r %1 --op=update --name=%2 --value=%3", record, name, value);
  299.  y2milestone("execute command - %1", command );
  300.  boolean ret = true;
  301.         map<string, any> retcode = (map<string, any>) SCR::Execute(.target.bash_output, command);
  302.     if (size(retcode["stderr"]:"")>0) {
  303.                 y2error("%1", retcode["stderr"]:"");
  304.                 ret =  false;
  305.                 }
  306. y2milestone("return value %1", ret);
  307.  return ret;
  308. }
  309.  
  310. // check if given target is connected
  311. global boolean connected(string rec_number){
  312.  boolean ret = false;
  313.  foreach(string row, sessions, {
  314.   if (issubstring(row, rec_number)){
  315.    ret = true;
  316.    break;
  317.   }
  318.  });
  319.  y2milestone("Target %1 connected:%2", rec_number, ret);
  320.  return ret;
  321. }
  322.  
  323. // change startup status (manual/automatic) for target
  324. global boolean setStartupStatus(string record, string status){
  325.  y2milestone("Set startup status for %1 to %2", record, status);
  326.  boolean ret = true;
  327.        map<string, any> retcode = (map<string, any>) SCR::Execute(.target.bash_output, 
  328.             sformat("iscsiadm -m node -r %1 --op=update --name=node.conn[0].startup --value=%2", record, status));
  329.     if (size(retcode["stderr"]:"")>0) return false;
  330.  return ret;
  331. }
  332.  
  333. // get status of open-iscsi
  334. boolean getServiceStatus(){
  335.  boolean ret = true;
  336.  if (Service::Status("open-iscsi") == 0) serviceStatus=true;
  337.  y2milestone("Service status = %1", serviceStatus);
  338.  // if not enabled, start it manually
  339.  if (!serviceStatus) Service::Start("open-iscsi");
  340.  return ret;
  341. }
  342.  
  343. // set startup status of open-iscsi
  344. boolean setServiceStatus(){
  345.  boolean ret = true;
  346. // if disabled and no connected targets - stop it
  347. // otherwise keep it running
  348.  if (!GetStartService()){
  349.      readSessions();
  350.      if (size(sessions)==0) {
  351.          y2milestone("No active sessions - stopping service");
  352.          Service::Stop("open-iscsi");
  353.         }
  354.     }
  355.  y2milestone("Status service for open-iscsi: %1", ret);
  356.  return ret;
  357. }
  358.  
  359. /**
  360.  * Read all iscsi-client settings
  361.  * @return true on success
  362.  */
  363. global boolean Read() {
  364.  
  365.     /* IscsiClient read dialog caption */
  366.     string caption = _("Initializing iSCSI Initiator Configuration");
  367.  
  368.     // TODO FIXME Set the right number of stages
  369.     integer steps = 4;
  370.  
  371.     integer sl = 500;
  372.     sleep(sl);
  373.  
  374.     // TODO FIXME Names of real stages
  375.     // We do not set help text here, because it was set outside
  376.     Progress::New( caption, " ", steps, [
  377.         /* Progress stage 1/3 */
  378.         _("Read the database"),
  379.         /* Progress stage 2/3 */
  380.         _("Read the previous settings"),
  381.         /* Progress stage 3/3 */
  382.         _("Detect the devices")
  383.     ], [
  384.         /* Progress step 1/3 */
  385.         _("Reading the database..."),
  386.         /* Progress step 2/3 */
  387.         _("Reading the previous settings..."),
  388.         /* Progress step 3/3 */
  389.         _("Detecting the devices..."),
  390.         /* Progress finished */
  391.         _("Finished")
  392.     ],
  393.     ""
  394.     );
  395.  
  396.     // check if user is root - must be root
  397.     if(!Confirm::MustBeRoot()) return false;
  398.     Progress::NextStage();
  399.     if(false) return false;
  400.     sleep(sl);
  401.  
  402.     Progress::NextStage();
  403.     // check if required package is installed
  404.     if(!installed_packages()) return false;
  405.     // check initiatorname - create it if no exists
  406.     y2milestone("Check initiator name");
  407.     if(!checkInitiatorName()) return false;
  408.     sleep(sl);
  409.  
  410.     if(Abort()) return false;
  411.     Progress::NextStep();
  412.     // read status of service
  413.     if(!getServiceStatus()) return false;
  414.     sleep(sl);
  415.  
  416.     // read current settings
  417.     if(Abort()) return false;
  418.     Progress::NextStage();
  419.     // read config file
  420.     if(readSessions()==false)
  421.     {
  422.     Report::Error( Message::CannotReadCurrentSettings() );
  423.     return false;
  424.     }
  425.     sleep(sl);
  426.  
  427.     if(Abort()) return false;
  428.     /* Progress finished */
  429.     Progress::NextStage();
  430.     sleep(sl);
  431.  
  432.     if(Abort()) return false;
  433.     modified = false;
  434.     return true;
  435. }
  436.  
  437. /**
  438.  * Write all iscsi-client settings
  439.  * @return true on success
  440.  */
  441. global boolean Write() {
  442.  
  443.     /* IscsiClient read dialog caption */
  444.     string caption = _("Saving iSCSI Initiator Configuration");
  445.  
  446.     // TODO FIXME And set the right number of stages
  447.     integer steps = 2;
  448.  
  449.     integer sl = 500;
  450.     sleep(sl);
  451.  
  452.     // TODO FIXME Names of real stages
  453.     // We do not set help text here, because it was set outside
  454.     Progress::New(caption, " ", steps, [
  455.         /* Progress stage 1/2 */
  456.         _("Write the settings"),
  457.         /* Progress stage 2/2 */
  458.         _("Run SuSEconfig")
  459.     ], [
  460.         /* Progress step 1/2 */
  461.         _("Writing the settings..."),
  462.         /* Progress step 2/2 */
  463.         _("Running SuSEconfig..."),
  464.         /* Progress finished */
  465.         _("Finished")
  466.     ],
  467.     ""
  468.     );
  469.  
  470.     if(Abort()) return false;
  471.     Progress::NextStage();
  472.     if(false) return false;
  473.     sleep(sl);
  474.  
  475.     if(Abort()) return false;
  476.     Progress::NextStage ();
  477.     if(false) return false;
  478.     sleep(sl);
  479.  
  480.     if(Abort()) return false;
  481.     Progress::NextStage();
  482.     sleep(sl);
  483.  
  484.     // set open-iscsi service status
  485.     if(!setServiceStatus()) return false;
  486.     return true;
  487. }
  488.  
  489. /**
  490.  * Get all iscsi-client settings from the first parameter
  491.  * (For use by autoinstallation.)
  492.  * @param settings The YCP structure to be imported.
  493.  * @return boolean True on success
  494.  */
  495. global boolean Import (map settings) {
  496.     // TODO FIXME: your code here (fill the above mentioned variables)...
  497.     return true;
  498. }
  499.  
  500. /**
  501.  * Dump the iscsi-client settings to a single map
  502.  * (For use by autoinstallation.)
  503.  * @return map Dumped settings (later acceptable by Import ())
  504.  */
  505. global map Export () {
  506.     // TODO FIXME: your code here (return the above mentioned variables)...
  507.     return $[];
  508. }
  509.  
  510. /**
  511.  * Create a textual summary and a list of unconfigured cards
  512.  * @return summary of the current configuration
  513.  */
  514. global list Summary() {
  515.     // TODO FIXME: your code here...
  516.     /* Configuration summary text for autoyast */
  517.     return [ _("Configuration summary..."), [] ];
  518. }
  519.  
  520. /**
  521.  * Create an overview table with all configured cards
  522.  * @return table items
  523.  */
  524. global list Overview() {
  525.     // TODO FIXME: your code here...
  526.     return [];
  527. }
  528.  
  529. /**
  530.  * Return packages needed to be installed and removed during
  531.  * Autoinstallation to insure module has all needed software
  532.  * installed.
  533.  * @return map with 2 lists.
  534.  */
  535. global map AutoPackages() {
  536.     // TODO FIXME: your code here...
  537.     return $[ "install":[], "remove":[] ];
  538. }
  539.  
  540.  
  541.  
  542.  
  543. /* EOF */
  544. }
  545.