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