[Freeipa-devel] External plugin integration

Alexander Bokovoy abokovoy at redhat.com
Fri Aug 5 11:58:19 UTC 2016


On Fri, 05 Aug 2016, Martin Basti wrote:
>
>
>On 04.08.2016 17:49, Alexander Bokovoy wrote:
>>Hi!
>>
>>I've stumbled into an interesting problem.
>>
>>Suppose, I have a plugin that adds schema and a subtree where entries it
>>manages will be stored. This subtree will have ACIs applied based on the
>>plugin permissions' configuration. Now, I put schema file in
>>/usr/ipa/share, and updates file in /usr/share/ipa/updates, and also add
>>plugin code to the ipaserver/plugins/ (let's say, rpm does it for me).
>>Next, I want to install IPA server. The install will run through up to
>>server upgrade phase which will fail because generation of ACIs will
>>reference schema attributes/classes which aren't loaded to the dirsrv by
>>installer. How to solve it?
>>Installer uses hard-coded list of schema files and this is a third-party
>>plugin, it needs to extend the list of active schema files.
>>
>>If we can define a place where third-party plugins could drop schema and
>>we just load everything from there before processing updates, it would
>>probably be enough.
>>
>
>TLDR: you don't without modifications in current IPA code, or it will 
>be huge hack
So far all I needed are following modifications which really boil down
to:
 - introduce /usr/share/ipa/schema.d to hold third-party schema files
 - add support to read the schema files from /usr/share/ipa/schema.d
   to dsintance upgrade step and to ipa-server-upgrade

That's all. Since I'm adding a new directory, I needed to update
Makefile.am and install/configure.ac which requires regeneration of
Makefile/configure files. You'd need to remove install/Makefile and run
'make bootstrap-autogen' to make sure the install/Makefile is recreated
and install/share/schema.d/Makefile is created.

>I think, this is a part of "Support of 3rd party plugins" effort, but 
>it has not been designed yet. I would like to avoid any ad-hoc 
>solution.
>Maybe we should create a desing page and gathering requirements, you 
>have a lot of them already :).
I'm working on the whole package for FleetCommander integration and I'll
produce a howto based on it. So far, there was no need to have anything
dramatic.

-- 
/ Alexander Bokovoy
-------------- next part --------------
From 6a6383d234607c33b402df93e923478e9b64c000 Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <abokovoy at redhat.com>
Date: Fri, 5 Aug 2016 13:04:19 +0300
Subject: [PATCH 2/2] WIP: support schema files from third-party plugins

Allow upgrade process to include schema files from third-party plugins
installed in /usr/share/ipa/schema.d/*.schema.

The directory /usr/shar/eipa/schema.d is owned by the server-common
subpackage and therefore third-party plugins should depend on
freeipa-server-common (ipa-server-common) package in their package
dependencies.
---
 freeipa.spec.in                     |  5 ++++-
 install/configure.ac                |  1 +
 install/share/Makefile.am           |  1 +
 install/share/schema.d/Makefile.am  | 16 ++++++++++++++++
 install/share/schema.d/README       | 11 +++++++++++
 ipaplatform/base/paths.py           |  1 +
 ipaserver/install/dsinstance.py     | 16 +++++++++++++++-
 ipaserver/install/server/upgrade.py |  3 +++
 8 files changed, 52 insertions(+), 2 deletions(-)
 create mode 100644 install/share/schema.d/Makefile.am
 create mode 100644 install/share/schema.d/README

diff --git a/freeipa.spec.in b/freeipa.spec.in
index 135e9c9..8acb3fc 100644
--- a/freeipa.spec.in
+++ b/freeipa.spec.in
@@ -871,6 +871,8 @@ mkdir -p %{buildroot}%{_sysconfdir}/cron.d
 
 mkdir -p %{buildroot}%{_sysconfdir}/ipa/custodia
 
+mkdir -p %{buildroot}%{_usr}/share/ipa/schema.d
+
 %endif # ONLY_CLIENT
 
 
@@ -1248,7 +1250,8 @@ fi
 %ghost %{_localstatedir}/lib/ipa/pki-ca/publish
 %ghost %{_localstatedir}/named/dyndb-ldap/ipa
 %dir %attr(0700,root,root) %{_sysconfdir}/ipa/custodia
-
+%dir %{_usr}/share/ipa/schema.d
+%attr(0644,root,root) %{_usr}/share/ipa/schema.d/README
 
 %files server-dns
 %defattr(-,root,root,-)
diff --git a/install/configure.ac b/install/configure.ac
index b5f77bf..81f17b9 100644
--- a/install/configure.ac
+++ b/install/configure.ac
@@ -88,6 +88,7 @@ AC_CONFIG_FILES([
     share/advise/Makefile
     share/advise/legacy/Makefile
     share/profiles/Makefile
+    share/schema.d/Makefile
     ui/Makefile
     ui/css/Makefile
     ui/src/Makefile
diff --git a/install/share/Makefile.am b/install/share/Makefile.am
index cd1c164..d8845ee 100644
--- a/install/share/Makefile.am
+++ b/install/share/Makefile.am
@@ -3,6 +3,7 @@ NULL =
 SUBDIRS =  				\
 	advise				\
 	profiles			\
+	schema.d			\
 	$(NULL)
 
 appdir = $(IPA_DATA_DIR)
diff --git a/install/share/schema.d/Makefile.am b/install/share/schema.d/Makefile.am
new file mode 100644
index 0000000..0fef87f
--- /dev/null
+++ b/install/share/schema.d/Makefile.am
@@ -0,0 +1,16 @@
+NULL =
+
+SUBDIRS =  				\
+	$(NULL)
+
+appdir = $(IPA_DATA_DIR)/schema.d
+app_DATA = README			\
+	$(NULL)
+
+EXTRA_DIST =				\
+	$(app_DATA)			\
+	$(NULL)
+
+MAINTAINERCLEANFILES =			\
+	*~				\
+	Makefile.in
diff --git a/install/share/schema.d/README b/install/share/schema.d/README
new file mode 100644
index 0000000..eb8c503
--- /dev/null
+++ b/install/share/schema.d/README
@@ -0,0 +1,11 @@
+This directory is indended to store schema files for 3rd-party plugins.
+
+Each schema file should be named NN-description.schema where NN is a number 00..90.
+
+The schema files from this directory are merged together with the core IPA
+schema files during the run of ipa-server-upgrade utility. Therefore, they are
+also installed when upgrade happens within the process of ipa-server-install.
+
+The directory is installed as /usr/share/ipa/schema.d and is owned by a
+freeipa-server-common package. Therefore, a 3rd-party plugin would need to
+depend on the freeipa-server-common package if it delivers the schema file(s).
diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py
index b1fedf5..fff55a3 100644
--- a/ipaplatform/base/paths.py
+++ b/ipaplatform/base/paths.py
@@ -354,6 +354,7 @@ class BasePathNamespace(object):
     IPA_CUSTODIA_SOCKET = '/run/httpd/ipa-custodia.sock'
     IPA_CUSTODIA_AUDIT_LOG = '/var/log/ipa-custodia.audit.log'
     IPA_GETKEYTAB = '/usr/sbin/ipa-getkeytab'
+    EXTERNAL_SCHEMA_DIR = '/usr/share/ipa/schema.d'
 
     @property
     def USER_CACHE_PATH(self):
diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py
index c93b3b4..2ffd9b4 100644
--- a/ipaserver/install/dsinstance.py
+++ b/ipaserver/install/dsinstance.py
@@ -180,6 +180,18 @@ def get_domain_level(api=api):
     return int(entry.single_value['ipaDomainLevel'])
 
 
+def get_all_external_schema_files(root):
+    """Get all schema files"""
+    f = []
+    for path, subdirs, files in os.walk(root):
+        for name in files:
+            if fnmatch.fnmatch(name, "*.schema"):
+                f.append(os.path.join(path, name))
+        if not recursive:
+           break
+    return f
+
+
 INF_TEMPLATE = """
 [General]
 FullMachineName=   $FQDN
@@ -656,7 +668,9 @@ class DsInstance(service.Service):
         conn.unbind()
 
     def apply_updates(self):
-        data_upgrade = upgradeinstance.IPAUpgrade(self.realm)
+        schema_files = get_all_external_schema_files(paths.EXTERNAL_SCHEMA_DIR)
+        data_upgrade = upgradeinstance.IPAUpgrade(self.realm,
+                                                  schema_files=schema_files)
         try:
             data_upgrade.create_instance()
         except Exception as e:
diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py
index 4342717..2d6b8cb 100644
--- a/ipaserver/install/server/upgrade.py
+++ b/ipaserver/install/server/upgrade.py
@@ -1817,6 +1817,9 @@ def upgrade():
     realm = api.env.realm
     schema_files = [os.path.join(ipautil.SHARE_DIR, f) for f
                     in dsinstance.ALL_SCHEMA_FILES]
+
+    schema_files.extend(dsinstance.get_all_external_schema_files(
+                        paths.EXTERNAL_SCHEMA_DIR))
     data_upgrade = IPAUpgrade(realm, schema_files=schema_files)
 
     try:
-- 
2.7.4



More information about the Freeipa-devel mailing list