Re: [389-devel] Instance discovery tools in lib389

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

> > 
> > Ultimately, I would like to see some of your new functionally go into 
> > the existing core module, and then write your tools based off of those.  
> > This way it can be leveraged outside of your "specific task" tools - for 
> > use in other new/future tools.  Of course I am specualting a bit, 
> > because I have not seen what you are working on yet.
> 
> You have already seen my work, and acked most of the functionality into the 
> core
> modules. Additionally the aci.py module is waiting in your inbox for informal
> review. 
> 
> For example: 
> 
> https://fedorahosted.org/389/ticket/48236 <- Will be used in conjunction with
> aci.py to evaluate and test aci functionality is working as expected, both in
> the aci evaluation engine in 389ds, but also from a semantic point of view of
> user acis
> 
> https://fedorahosted.org/389/ticket/48238 <- Is all the functionality needed 
> to
> make the schema query tool I was discussing before.

Here is a patch with an example of what I have in mind. It's not perfected, or
polished, but it demonstrates what I have in mind.

To use it:

python clitools/ds_list_instances.py

python clitools/ds_schema_attributetype_list.py -i "instance name"

The main details are:

* It must be run on the same system as the ds instance.
* It respects PREFIX for your DS instances.
* This tool requires permissions to read dse.ldif of the instance. It currently
doesn't handle permission denied gracefully, as after all it's a POC.

I hope this demonstrates how I want to tie together the other contributions I
have made into tools, but also making it possible to test other aspects of
389ds. 

Comments and advice welcome.

-- 
William Brown <william@xxxxxxxxxxxxxxxx>
From f72ea4698550dbea8fcb03ff68b5b54dbc9efdcc Mon Sep 17 00:00:00 2001
From: William Brown <wililam@xxxxxxxxxxxxxxx>
Date: Thu, 6 Aug 2015 10:11:25 +0930
Subject: [PATCH] Example of commandline tools implementation for listing all
 attribute types and instances

---
 clitools/ds_list_instances.py            | 17 ++++++++++
 clitools/ds_schema_attributetype_list.py | 21 ++++++++++++
 clitools/helper.py                       | 24 +++++++++++++
 lib389/__init__.py                       | 58 +++++++++++++++++++++++++++-----
 lib389/_constants.py                     | 15 +++++++++
 5 files changed, 126 insertions(+), 9 deletions(-)
 create mode 100644 clitools/ds_list_instances.py
 create mode 100644 clitools/ds_schema_attributetype_list.py
 create mode 100644 clitools/helper.py

diff --git a/clitools/ds_list_instances.py b/clitools/ds_list_instances.py
new file mode 100644
index 0000000..9c2a14a
--- /dev/null
+++ b/clitools/ds_list_instances.py
@@ -0,0 +1,17 @@
+#!/usr/bin/python
+
+from lib389 import DirSrv
+from lib389._constants import *
+
+def list_instances():
+    # Remember, the prefix can be set with the os environment
+    allds = DirSrv()
+    instances = allds.list(all=True)
+    print('Instances on this system:')
+    for instance in instances:
+        print(instance[CONF_SERVER_ID])
+
+if __name__ == '__main__':
+    list_instances()
+
+
diff --git a/clitools/ds_schema_attributetype_list.py b/clitools/ds_schema_attributetype_list.py
new file mode 100644
index 0000000..11c5adc
--- /dev/null
+++ b/clitools/ds_schema_attributetype_list.py
@@ -0,0 +1,21 @@
+#!/usr/bin/python
+
+from helper import clitools_parser, get_instance_dict, get_rootdn_pass
+from lib389 import DirSrv
+from lib389._constants import *
+import ldap
+
+
+def schema_attributetype_list(args):
+    inst = get_instance_dict(args.instance)[0]
+    get_rootdn_pass(inst)
+    ds = DirSrv()
+    ds.allocate(inst)
+    ds.open()
+    for attributetype in ds.schema.get_attributetypes():
+        print(attributetype)
+
+if __name__ == '__main__':
+    # Do some arg parse stuff
+    args = clitools_parser.parse_args()
+    schema_attributetype_list(args)
diff --git a/clitools/helper.py b/clitools/helper.py
new file mode 100644
index 0000000..4dff0dd
--- /dev/null
+++ b/clitools/helper.py
@@ -0,0 +1,24 @@
+# Probably need some helpers for argparse and instance selection
+
+from argparse import ArgumentParser
+from getpass import getpass
+from lib389 import DirSrv
+from lib389._constants import *
+
+def get_instance_dict(instance):
+    allds = DirSrv()
+    return allds.list(serverid=instance)
+
+def get_rootdn_pass(instance):
+    #There is a dict get key thing somewhere ...
+    if instance.get(SER_ROOT_PW, None) is None:
+        instance[SER_ROOT_PW] = getpass('Enter password for %s on instance %s: ' % (instance[SER_ROOT_DN], instance[SER_SERVERID_PROP]))
+    return
+
+def _clitools_parser():
+    parser = ArgumentParser()
+    parser.add_argument('--instance', '-i', help='The name of the DS instance to connect to and work upon.')
+    return parser
+
+clitools_parser = _clitools_parser()
+
diff --git a/lib389/__init__.py b/lib389/__init__.py
index 10bf0df..a516992 100644
--- a/lib389/__init__.py
+++ b/lib389/__init__.py
@@ -374,7 +374,7 @@ class DirSrv(SimpleLDAPObject):
         self.timeout = timeout
 
         # Reset the args (py.test reuses the args_instance for each test case)
-        args_instance[SER_DEPLOYED_DIR] = os.environ.get('PREFIX', None)
+        args_instance[SER_DEPLOYED_DIR] = os.environ.get('PREFIX', '/')
         args_instance[SER_BACKUP_INST_DIR] = os.environ.get('BACKUPDIR', DEFAULT_BACKUPDIR)
         args_instance[SER_ROOT_DN] = DN_DM
         args_instance[SER_ROOT_PW] = PW_DM
@@ -386,6 +386,12 @@ class DirSrv(SimpleLDAPObject):
         args_instance[SER_USER_ID] = None
         args_instance[SER_GROUP_ID] = None
 
+        # We allocate a "default" prefix here which allows an un-allocate or un-instantiated DirSrv
+        # instance to be able to do an an instance discovery. For example:
+        #  ds = lib389.DirSrv()
+        #  ds.list(all=True)
+        self.prefix = args_instance[SER_DEPLOYED_DIR]
+
         self.__wrapmethods()
         self.__add_brookers__()
 
@@ -440,7 +446,7 @@ class DirSrv(SimpleLDAPObject):
         self.serverid  = args.get(SER_SERVERID_PROP, None)
         self.groupid   = args.get(SER_GROUP_ID, self.userid)
         self.backupdir = args.get(SER_BACKUP_INST_DIR, DEFAULT_BACKUPDIR)
-        self.prefix    = args.get(SER_DEPLOYED_DIR) or '/'
+        self.prefix    = args.get(SER_DEPLOYED_DIR)
 
         # Those variables needs to be revisited (sroot for 64 bits)
         #self.sroot     = os.path.join(self.prefix, "lib/dirsrv")
@@ -471,7 +477,7 @@ class DirSrv(SimpleLDAPObject):
 
         return server
 
-    def list(self, all=False):
+    def list(self, all=False, serverid=None):
         """
             Returns a list dictionary. For a created instance that is on the local file system
             (e.g. <prefix>/etc/dirsrv/slapd-*), it exists a file describing its properties
@@ -489,6 +495,8 @@ class DirSrv(SimpleLDAPObject):
 
             @param all - True or False . default is [False]
 
+            @param instance - The name of the instance to retrieve or None for the current instance
+
             @return list of dictionaries, each of them containing instance properities
 
             @raise IOError - if the file containing the properties is not foundable or readable
@@ -503,7 +511,7 @@ class DirSrv(SimpleLDAPObject):
                 return 1
             return 0
 
-        def _parse_configfile(filename=None):
+        def _parse_configfile(filename=None, serverid=None):
             '''
                 This method read 'filename' and build a dictionary with
                 CONF_* properties
@@ -515,6 +523,9 @@ class DirSrv(SimpleLDAPObject):
                 raise IOError('invalid file name or rights: %s' % filename)
 
             prop = {}
+            prop[CONF_SERVER_ID] = serverid
+            prop[SER_SERVERID_PROP] = serverid
+            prop[SER_DEPLOYED_DIR] = self.prefix
             myfile = open(filename, 'r')
             for line in myfile:
                 # retrieve the value in line:: <PROPNAME>=<string> [';' export <PROPNAME>]
@@ -545,6 +556,31 @@ class DirSrv(SimpleLDAPObject):
                     if test_and_set(prop, property, variable, value):
                         break
 
+            # Now, we have passed the sysconfig environment file.
+            #  read in and parse the dse.ldif to determine our SER_* values.
+            # probably should use path join?
+            dsefile = '%s/dse.ldif' % prop[CONF_CONFIG_DIR]
+            if os.path.exists(dsefile):
+                ldifconn = LDIFConn(dsefile)
+                configentry = ldifconn.get(DN_CONFIG)
+                for key in args_dse_keys:
+                    prop[key] = configentry.getValue(args_dse_keys[key])
+                #SER_HOST            (host) nsslapd-localhost
+                #SER_PORT            (port) nsslapd-port
+                #SER_SECURE_PORT     (sslport) nsslapd-secureport
+                #SER_ROOT_DN         (binddn) nsslapd-rootdn
+                #SER_ROOT_PW         (bindpw) We can't do this
+                #SER_CREATION_SUFFIX (creation_suffix) nsslapd-defaultnamingcontext
+                #SER_USER_ID         (userid) nsslapd-localuser
+                #SER_SERVERID_PROP   (serverid) Already have this
+                #SER_GROUP_ID        (groupid) ???
+                #SER_DEPLOYED_DIR    (prefix) Already provided to do the discovery
+                #SER_BACKUP_INST_DIR (backupdir) nsslapd-bakdir <<-- maybe?
+                # We need to convert these two to int
+                #  because other routines get confused if we don't
+                for intkey in [SER_PORT, SER_SECURE_PORT]:
+                    if prop[intkey] is not None:
+                        prop[intkey] = int(prop[intkey])
             return prop
 
         def search_dir(instances, pattern, stop_value=None):
@@ -565,6 +601,7 @@ class DirSrv(SimpleLDAPObject):
                                         not find it.
             '''
             added = False
+            print(pattern)
             for instance in glob.glob(pattern):
                 serverid = os.path.basename(instance)[len(DEFAULT_ENV_HEAD):]
 
@@ -575,7 +612,7 @@ class DirSrv(SimpleLDAPObject):
                 # it is found, store its properties in the list
                 if stop_value:
                     if stop_value == serverid:
-                        instances.append(_parse_configfile(instance))
+                        instances.append(_parse_configfile(instance, serverid))
                         added = True
                         break
                     else:
@@ -583,7 +620,7 @@ class DirSrv(SimpleLDAPObject):
                         continue
                 else:
                     # we are not looking for a specific value, just add it
-                    instances.append(_parse_configfile(instance))
+                    instances.append(_parse_configfile(instance, serverid))
 
             return added
 
@@ -600,7 +637,10 @@ class DirSrv(SimpleLDAPObject):
         #    inst: <prefix>/etc/dirsrv/slapd-<serverid>  (conf)
         #
 
-        prefix = self.prefix or '/'
+        # Don't need a default value now since it's set in init.
+        prefix = self.prefix
+        if serverid is None and hasattr(self, 'serverid'):
+            serverid = self.serverid
 
         # first identify the directories we will scan
         confdir = os.getenv('INITCONFIGDIR')
@@ -632,7 +672,7 @@ class DirSrv(SimpleLDAPObject):
             # first check the private repository
             if privconfig_head:
                 pattern = "%s*" % os.path.join(privconfig_head, DEFAULT_ENV_HEAD)
-                found = search_dir(instances, pattern, self.serverid)
+                found = search_dir(instances, pattern, serverid)
                 if len(instances) > 0:
                     self.log.info("List from %s" % privconfig_head)
                     for instance in instances:
@@ -647,7 +687,7 @@ class DirSrv(SimpleLDAPObject):
             # second, if not already found, search the system repository
             if not found:
                 pattern = "%s*" % os.path.join(sysconfig_head, DEFAULT_ENV_HEAD)
-                search_dir(instances, pattern, self.serverid)
+                search_dir(instances, pattern, serverid)
                 if len(instances) > 0:
                     self.log.info("List from %s" % privconfig_head)
                     for instance in instances:
diff --git a/lib389/_constants.py b/lib389/_constants.py
index 2b4c6d5..96b008e 100644
--- a/lib389/_constants.py
+++ b/lib389/_constants.py
@@ -78,6 +78,7 @@ ENV_SYSCONFIG_DIR = '/etc/sysconfig'
 ENV_LOCAL_DIR = '.dirsrv'
 
 # CONFIG file (<prefix>/etc/sysconfig/dirsrv-* or $HOME/.dirsrv/dirsrv-*) keywords
+CONF_SERVER_ID     = 'SERVER_ID'
 CONF_SERVER_DIR    = 'SERVER_DIR'
 CONF_SERVERBIN_DIR = 'SERVERBIN_DIR'
 CONF_CONFIG_DIR    = 'CONFIG_DIR'
@@ -428,3 +429,17 @@ args_instance = {
                    SER_SERVERID_PROP: "template",
                    SER_CREATION_SUFFIX: DEFAULT_SUFFIX}
 
+# Helper for linking dse.ldif values to the parse_config function
+args_dse_keys = {
+                SER_HOST: 'nsslapd-localhost',
+                SER_PORT: 'nsslapd-port',
+                SER_SECURE_PORT: 'nsslapd-secureport',
+                SER_ROOT_DN: 'nsslapd-rootdn',
+                #SER_ROOT_PW         (bindpw) We can't do this
+                SER_CREATION_SUFFIX: 'nsslapd-defaultnamingcontext',
+                SER_USER_ID: 'nsslapd-localuser',
+                #SER_SERVERID_PROP   (serverid) Already have this set in other areas.
+                #SER_GROUP_ID        (groupid) ???
+                #SER_DEPLOYED_DIR    (prefix) Already provided to do the discovery
+                #SER_BACKUP_INST_DIR (backupdir) nsslapd-bakdir <<-- maybe?
+}
-- 
2.4.3

--
389-devel mailing list
389-devel@xxxxxxxxxxxxxxxxxxxxxxx
https://admin.fedoraproject.org/mailman/listinfo/389-devel

[Index of Archives]     [Fedora Directory Announce]     [Fedora Users]     [Older Fedora Users Mail]     [Fedora Advisory Board]     [Fedora Security]     [Fedora Devel Java]     [Fedora Desktop]     [ATA RAID]     [Fedora Marketing]     [Fedora Mentors]     [Fedora Package Review]     [Fedora Art]     [Fedora Music]     [Fedora Packaging]     [CentOS]     [Fedora SELinux]     [Big List of Linux Books]     [KDE Users]     [Fedora Art]     [Fedora Docs]

  Powered by Linux