#50290 Ticket 50289 - Fix various database UI issues
Closed 3 years ago by spichugi. Opened 5 years ago by mreynolds.
mreynolds/389-ds-base ui-fixes  into  master

file modified
+8 -7
@@ -1486,7 +1486,7 @@ 

                  Slapi_Entry *e,

                  Slapi_Entry *eAfter __attribute__((unused)),

                  int *returncode,

-                 char *returntext __attribute__((unused)),

+                 char *returntext,

                  void *arg __attribute__((unused)))

  {

      Slapi_Backend *be = NULL;
@@ -1529,18 +1529,19 @@ 

      }

      slapi_ch_free_string(&cookie);

      if (NULL == be || NULL == be->be_database->plg_db2archive) {

-         slapi_log_err(SLAPI_LOG_ERR,

-                       "task_backup_add", "no db2archive function defined.\n");

+         PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,

+                 "no db2archive function defined.  There is no backend/suffix present");

+         slapi_log_err(SLAPI_LOG_ERR, "task_backup_add", "Error: %s\n", returntext);

          *returncode = LDAP_UNWILLING_TO_PERFORM;

          rv = SLAPI_DSE_CALLBACK_ERROR;

          goto out;

      }

  

      if (!SLAPI_PLUGIN_IS_V3(be->be_database)) {

-         slapi_log_err(SLAPI_LOG_ERR,

-                       "task_backup_add", "Can't perform an backup with pre-V3 "

-                                          "backend plugin %s\n",

-                       be->be_database->plg_name);

+         PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,

+                 "Can't perform an backup with pre-V3 backend plugin %s\n",

+                 be->be_database->plg_name);

+         slapi_log_err(SLAPI_LOG_ERR, "task_backup_add", "Error: %s\n", returntext);

          *returncode = LDAP_UNWILLING_TO_PERFORM;

          rv = SLAPI_DSE_CALLBACK_ERROR;

          goto out;

@@ -97,11 +97,13 @@ 

      }

  

      componentWillMount () {

-         this.loadGlobalConfig();

-         this.loadChainingConfig();

-         this.loadLDIFs();

-         this.loadBackups();

-         this.loadSuffixList();

+         if (!this.state.loaded) {

+             this.loadGlobalConfig();

+             this.loadChainingConfig();

+             this.loadLDIFs();

+             this.loadBackups();

+             this.loadSuffixList();

+         }

      }

  

      componentDidMount() {
@@ -183,7 +185,7 @@ 

                          }), this.setState({configUpdated: 0}));

                  })

                  .fail(err => {

-                     this.props.addNotification(

+                     this.addNotification(

                          "error",

                          `Error loading database configuration - ${err}`

                      );
@@ -269,7 +271,7 @@ 

                      ), this.loadAvailableControls());

                  })

                  .fail(err => {

-                     this.props.addNotification(

+                     this.addNotification(

                          "error",

                          `Error loading default chaining configuration - ${err}`

                      );
@@ -313,11 +315,14 @@ 

              "dsconf", "-j", "ldapi://%2fvar%2frun%2fslapd-" + this.props.serverId + ".socket",

              "backend", "get-tree",

          ];

-         log_cmd("getTree", "Start building the suffix tree", cmd);

+         log_cmd("loadSuffixTree", "Start building the suffix tree", cmd);

          cockpit

                  .spawn(cmd, { superuser: true, err: "message" })

                  .done(content => {

-                     let treeData = JSON.parse(content);

+                     let treeData = [];

+                     if (content != "") {

+                         treeData = JSON.parse(content);

+                     }

                      let basicData = [

                          {

                              text: "Global Database Configuration",
@@ -356,7 +361,6 @@ 

                      this.setState(() => ({

                          nodes: basicData,

                          node_name: current_node,

- 

                      }), this.update_tree_nodes);

                  });

      }
@@ -770,7 +774,7 @@ 

                      });

                  })

                  .fail(err => {

-                     this.props.addNotification(

+                     this.addNotification(

                          "error",

                          `Error loading indexes for ${suffix} - ${err}`

                      );
@@ -924,7 +928,7 @@ 

                                                          });

                                                      })

                                                      .fail(err => {

-                                                         this.props.addNotification(

+                                                         this.addNotification(

                                                              "error",

                                                              `Error loading indexes for ${suffix} - ${err}`

                                                          );
@@ -960,7 +964,7 @@ 

          const cmd = [

              "dsctl", "-j", this.props.serverId, "backups"

          ];

-         log_cmd("loadLDIFs", "Load Backups", cmd);

+         log_cmd("loadBackups", "Load Backups", cmd);

          cockpit

                  .spawn(cmd, { superuser: true, err: "message" })

                  .done(content => {
@@ -995,7 +999,7 @@ 

                      });

                  })

                  .fail(err => {

-                     this.props.addNotification(

+                     this.addNotification(

                          "error",

                          `Failed to get attributes - ${err}`

                      );

@@ -309,13 +309,6 @@ 

  // all the save functions for all the pages here.  This is not used for modal forms

  function save_all () {

    save_config();  // Server Config Page

-   //

-   // TODO:

-   //   save_chaining();

-   //   save_chaining_suffix();

-   //   save_global_backend();

-   //   save_suffix();

-   //   save_security();

  }

  

  function load_repl_suffix_dropdowns() {
@@ -351,7 +344,7 @@ 

  

  var loading_cfg = 0;

  

- function load_config (){

+ function load_config (refresh){

    // If we are currently loading config don't do it twice

    if (loading_cfg == 1){

      return;
@@ -418,6 +411,13 @@ 

          $("#server-config").show();

          clearInterval(loading_config);

          loading_cfg = 0;

+ 

+         if (refresh) {

+             // Reload reactJS pages by clicking dummy element

+             let reload_el = document.getElementById('reload-page');

+             reload_el.click();

+         }

+ 

          console.log("Completed configuration initialization.");

        }

      }, 300);

@@ -14,16 +14,18 @@ 

                  .getElementById("select-server")

                  .value.replace("slapd-", "");

      }

+     let d = new Date();

+     let n = d.getTime(); // might not be needed MARK

  

      // Plugins Tab

      ReactDOM.render(

-         <Plugins serverId={serverIdElem} />,

+         <Plugins serverId={serverIdElem} key={n} />,

          document.getElementById("plugins")

      );

  

      // Database tab

      ReactDOM.render(

-         <Database serverId={serverIdElem} />,

+         <Database serverId={serverIdElem} key={n} />,

          document.getElementById("database")

      );

  }
@@ -45,10 +47,7 @@ 

                      .getElementById("select-server")

                      .addEventListener("change", renderReactWrapper);

              document

-                     .getElementById("start-server-btn")

-                     .addEventListener("click", renderReactWrapper);

-             document

-                     .getElementById("restart-server-btn")

+                     .getElementById("reload-page")

                      .addEventListener("click", renderReactWrapper);

              document

                      .getElementById("remove-server-btn")

@@ -35,6 +35,7 @@ 

  </head>

  

  <body>

+   <div id="reload-page" hidden></div>

    <div id="loading-page" class="ds-center ds-loading-spinner" hidden>

      <h3 id="loading-msg">Loading Directory Server Configuration...</h3>

      <p><span class="spinner spinner-lg spinner-inline"></span></p>

@@ -86,6 +86,7 @@ 

          this.setState({

              showExportModal: true,

              exportSpinner: false,

+             ldifName: "",

              ldifSuffix: this.props.suffixes[0]

          });

      }
@@ -147,7 +148,8 @@ 

      showBackupModal () {

          this.setState({

              showBackupModal: true,

-             backupSpinning: false

+             backupSpinning: false,

+             backupName: ""

          });

      }

  
@@ -289,10 +291,15 @@ 

              backupSpinning: true

          });

  

-         const cmd = [

+         let cmd = [

              "dsconf", "-j", "ldapi://%2fvar%2frun%2fslapd-" + this.props.serverId + ".socket",

-             "backup", "create", this.state.backupName

+             "backup", "create"

          ];

+ 

+         if (this.state.backupName != "") {

+             cmd.push(this.state.backupName);

+         }

+ 

          log_cmd("doBackup", "Add backup task", cmd);

          cockpit

                  .spawn(cmd, { superuser: true, err: "message" })
@@ -615,7 +622,7 @@ 

                                  </Col>

                              </Row>

                              <p />

-                             <Row title="Name of exported LDIF file">

+                             <Row title="Name of exported LDIF file, if left blank the data and time will be used as the file name">

                                  <Col sm={3}>

                                      <ControlLabel>LDIF File Name</ControlLabel>

                                  </Col>
@@ -691,7 +698,7 @@ 

                      </Modal.Header>

                      <Modal.Body>

                          <Form horizontal autoComplete="off">

-                             <Row title="LDIF file to import">

+                             <Row title="Backup name, if left blank the date and time will be used as the name">

                                  <Col sm={3}>

                                      <ControlLabel>Backup Name</ControlLabel>

                                  </Col>

@@ -182,7 +182,7 @@ 

                  })

                  .fail(err => {

                      if (err != 0) {

-                         console.error("pluginList failed", err);

+                         console.log("pluginList failed", err);

                      }

                      this.toggleLoading();

                  });

@@ -416,7 +416,7 @@ 

    done(function(status_data) {

      var status_json = JSON.parse(status_data);

      if (status_json.running == true) {

-       var cmd = [DSCONF, server_inst, 'backup', 'create',  backup_name];

+       var cmd = [DSCONF, "-j", server_inst, 'backup', 'create',  backup_name];

        log_cmd('#ds-backup-btn (click)', 'Backup server instance', cmd);

        cockpit.spawn(cmd, { superuser: true, "err": "message", "environ": [ENV]}).

        done(function(data) {
@@ -471,7 +471,7 @@ 

            log_cmd('#start-server-btn (click)', 'Start server instance', cmd);

            cockpit.spawn(cmd, { superuser: true, "err": "message", "environ": [ENV]}).done(function(data) {

              $("#start-instance-form").modal('toggle');

-             load_config();

+             load_config(true);

              popup_success("Started instance \"" + server_id + "\"");

            }).fail(function(data) {

              $("#start-instance-form").modal('toggle');
@@ -497,13 +497,13 @@ 

  

  

          document.getElementById("restart-server-btn").addEventListener("click", function() {

-           $("#ds-restart-inst").html("<span class=\"spinner spinner-xs spinner-inline\"></span> Retarting instance <b>" + server_id + "</b>...");

+           $("#ds-restart-inst").html("<span class=\"spinner spinner-xs spinner-inline\"></span> Restarting instance <b>" + server_id + "</b>...");

            $("#restart-instance-form").modal('toggle');

            var cmd = [DSCTL, server_inst, 'restart'];

            log_cmd('#restart-server-btn (click)', 'Restart server instance', cmd);

            cockpit.spawn(cmd, { superuser: true, "err": "message", "environ": [ENV]}).done(function(data) {

              $("#restart-instance-form").modal('toggle');

-             load_config();

+             load_config(true);

              popup_success("Restarted instance \"" + server_id + "\"");

            }).fail(function(data) {

              $("#restart-instance-form").modal('toggle');

@@ -480,8 +480,20 @@ 

          :returns: DSLdapObject of the created entry

          """

  

+         # normalize suffix (remove spaces between comps)

+         if dn is not None:

+             dn_comps = ldap.dn.explode_dn(dn.lower())

+             dn = ",".join(dn_comps)

+ 

+         if properties is not None:

+             suffix_dn = properties['nsslapd-suffix'].lower()

+             dn_comps = ldap.dn.explode_dn(suffix_dn)

+             ndn = ",".join(dn_comps)

+             properties['nsslapd-suffix'] = ndn

+ 

          sample_entries = properties.pop(BACKEND_SAMPLE_ENTRIES, False)

          parent_suffix = properties.pop('parent', False)

+ 

          # Okay, now try to make the backend.

          super(Backend, self).create(dn, properties, basedn)

  
@@ -798,6 +810,8 @@ 

  

          task = ExportTask(self._instance)

          task_properties = {'nsInstance': be_names}

+         if ldif == "":

+             ldif = None

          if ldif is not None and not ldif.startswith("/"):

              if ldif.endswith(".ldif"):

                  task_properties['nsFilename'] = os.path.join(self._instance.ds_paths.ldif_dir, ldif)

@@ -376,9 +376,14 @@ 

      for be in be_insts:

          suffix = be.get_attr_val_utf8_l('nsslapd-suffix')

          be_name = be.get_attr_val_utf8('cn')

-         mt = be._mts.get(suffix)

+         try:

+             mt = be._mts.get(suffix)

+         except ldap.NO_SUCH_OBJECT:

+             log.debug("Failed to find the mapping tree entry using this suffix: {}".format(suffix))

+             continue

          sub = mt.get_attr_val_utf8_l('nsslapd-parent-suffix')

          if sub is not None:

+             # Skip sub suffixes for now, we will get them later

              continue

          nodes.append(build_node(suffix, be_name))

  

file modified
+42 -42
@@ -24,48 +24,48 @@ 

      def __init__(self, instance):

          self._instance = instance

          self.log = instance.log

-         self.pwp_attributes = [

-             'passwordstoragescheme',

-             'passwordChange',

-             'passwordMustChange',

-             'passwordHistory',

-             'passwordInHistory',

-             'passwordAdminDN',

-             'passwordTrackUpdateTime',

-             'passwordWarning',

-             'passwordMaxAge',

-             'passwordMinAge',

-             'passwordExp',

-             'passwordGraceLimit',

-             'passwordSendExpiringTime',

-             'passwordLockout',

-             'passwordUnlock',

-             'passwordMaxFailure',

-             'passwordLockoutDuration',

-             'passwordResetFailureCount',

-             'passwordCheckSyntax',

-             'passwordMinLength',

-             'passwordMinDigits',

-             'passwordMinAlphas',

-             'passwordMinUppers',

-             'passwordMinLowers',

-             'passwordMinSpecials',

-             'passwordMaxRepeats',

-             'passwordMin8bit',

-             'passwordMinCategories',

-             'passwordMinTokenLength',

-             'passwordDictPath',

-             'passwordDictCheck',

-             'passwordPalindrome',

-             'passwordMaxSequence',

-             'passwordMaxClassChars',

-             'passwordMaxSeqSets',

-             'passwordBadWords',

-             'passwordUserAttributes',

-             'passwordIsGlobalPolicy',

-             'nsslapd-pwpolicy-local',

-             'nsslapd-allow-hashed-passwords'

-         ]

+         self.arg_to_attr = {

+             'pwdlocal': 'nsslapd-pwpolicy-local',

+             'pwdscheme': 'passwordstoragescheme',

+             'pwdchange': 'passwordChange',

+             'pwdmustchange': 'passwordMustChange',

+             'pwdhistory': 'passwordHistory',

+             'pwdhistorycount': 'passwordInHistory',

+             'pwdadmin': 'passwordAdminDN',

+             'pwdtrack': 'passwordTrackUpdateTime',

+             'pwdwarning': 'passwordWarning',

+             'pwdisglobal': 'passwordIsGlobalPolicy',

+             'pwdexpire': 'passwordExp',

+             'pwdmaxage': 'passwordMaxAge',

+             'pwdminage': 'passwordMinAge',

+             'pwdgracelimit': 'passwordGraceLimit',

+             'pwdsendexpiring': 'passwordSendExpiringTime',

+             'pwdlockout': 'passwordLockout',

+             'pwdunlock': 'passwordUnlock',

+             'pwdlockoutduration': 'passwordLockoutDuration',

+             'pwdmaxfailures': 'passwordMaxFailure',

+             'pwdresetfailcount': 'passwordResetFailureCount',

+             'pwdchecksyntax': 'passwordCheckSyntax',

+             'pwdminlen': 'passwordMinLength',

+             'pwdmindigits': 'passwordMinDigits',

+             'pwdminalphas': 'passwordMinAlphas',

+             'pwdminuppers': 'passwordMinUppers',

+             'pwdminlowers': 'passwordMinLowers',

+             'pwdminspecials': 'passwordMinSpecials',

+             'pwdmin8bits': 'passwordMin8bit',

+             'pwdmaxrepeats': 'passwordMaxRepeats',

+             'pwdpalindrome': 'passwordPalindrome',

+             'pwdmaxseq': 'passwordMaxSequence',

+             'pwdmaxseqsets': 'passwordMaxSeqSets',

+             'pwdmaxclasschars': 'passwordMaxClassChars',

+             'pwdmincatagories': 'passwordMinCategories',

+             'pwdmintokenlen': 'passwordMinTokenLength',

+             'pwdbadwords': 'passwordBadWords',

+             'pwduserattrs': 'passwordUserAttributes',

+             'pwddictcheck': 'passwordDictCheck',

+             'pwddictpath': 'passwordDictPath',

+             'pwdallowhash': 'nsslapd-allow-hashed-passwords'

+         }

  

      def is_subtree_policy(self, dn):

          """Check if the entry has a subtree password policy.  If we can find a

Description:

Fixed these issues:

Also fixed issue where if you start an instance in UI the configuration is correctly loaded.

https://pagure.io/389-ds-base/issue/50289

I have a weird (empty line) error while trying to perform instance backup task from UI while the instance doesn't have any suffixes.
The screenshot:
https://drive.google.com/file/d/1IuPag3CiEf8yfzEUtQyIsWr4QzCI_VCa/view?usp=sharing

Also, dsconf backup gives me unwilling to perform exception:

# dsconf localhost backup create test_backup

Error: {'desc': 'Server is unwilling to perform'}

Though the task is created:

dn: cn=backup_2019-03-19T18:18:59.554265,cn=backup,cn=tasks,cn=config
cn: backup_2019-03-19T18:18:59.554265
nsArchiveDir: /var/lib/dirsrv/slapd-localhost/bak/test_backup
nsDatabaseType: ldbm database
objectclass: top
objectclass: extensibleObject

rebased onto a60bda60ea0e2dc48debdbabbd21a73d2fba1d3e

5 years ago

LGTM!

P.S. sorry for late review. The notification email got lost somehow.

rebased onto 395a4a2

5 years ago

Pull-Request has been merged by mreynolds

5 years ago

389-ds-base is moving from Pagure to Github. This means that new issues and pull requests
will be accepted only in 389-ds-base's github repository.

This pull request has been cloned to Github as issue and is available here:
- https://github.com/389ds/389-ds-base/issues/3349

If you want to continue to work on the PR, please navigate to the github issue,
download the patch from the attachments and file a new pull request.

Thank you for understanding. We apologize for all inconvenience.

Pull-Request has been closed by spichugi

3 years ago