domain.py: Add a schemaupgrade option to apply missing 2008R2 schema
authorTim Beale <timbeale@catalyst.net.nz>
Thu, 5 Oct 2017 03:16:30 +0000 (16:16 +1300)
committerAndrew Bartlett <abartlet@samba.org>
Thu, 14 Dec 2017 07:20:15 +0000 (08:20 +0100)
We've identified some cases where we've gotten our implementation of the
2008R2 schema wrong. We can fix these up for new provisions going
forward, but it'd be nice to have some way of fixing up the schema on
existing DCs.

A lot of what we're missing is already documented in Microsoft's
Sch45.ldf file:
https://technet.microsoft.com/en-us/library/dd378890(v=ws.10).aspx

Unfortunately we can't just apply the Sch45.ldf file using the existing
'samba-tool domain schema-upgrade' option because:
- We have got some of the Sch45.ldf changes, just not all of them.
- We already say the Samba schema objectVersion is 47 (2008R2), so
  there's no way to tell if the Samba instance does or doesn't have the
  missing changes (apart from querying each change).

We may want to add this to dbcheck eventually, but the simplest
implementation option for now is to extend the new schemaupgrade command
to allow us to specify a particular .LDF file to apply.

Signed-off-by: Tim Beale <timbeale@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
python/samba/netcmd/domain.py

index c34a438..6ec16e5 100644 (file)
@@ -3927,7 +3927,9 @@ class cmd_domain_schema_upgrade(Command):
         Option("--schema", type="choice", metavar="SCHEMA",
                choices=["2012", "2012_R2"],
                help="The schema file to upgrade to. Default is (Windows) 2012_R2.",
-               default="2012_R2")
+               default="2012_R2"),
+        Option("--ldf-file", type=str, default=None,
+                help="Just apply the schema updates in the adprep/.LDF file(s) specified")
     ]
 
     def _apply_updates_in_file(self, samdb, ldif_file):
@@ -4045,6 +4047,7 @@ class cmd_domain_schema_upgrade(Command):
         creds = credopts.get_credentials(lp)
         H = kwargs.get("H")
         target_schema = kwargs.get("schema")
+        ldf_files = kwargs.get("ldf_file")
 
         samdb = SamDB(url=H, session_info=system_session(), credentials=creds, lp=lp)
 
@@ -4054,16 +4057,25 @@ class cmd_domain_schema_upgrade(Command):
             print("Temporarily overriding 'dsdb:schema update allowed' setting")
             updates_allowed_overriden = True
 
-        # work out the version of the target schema we're upgrading to
-        end = Schema.get_version(target_schema)
+        # if specific LDIF files were specified, just apply them
+        if ldf_files:
+            schema_updates = ldf_files.split(",")
+        else:
+            schema_updates = []
+
+            # work out the version of the target schema we're upgrading to
+            end = Schema.get_version(target_schema)
 
-        # work out the version of the schema we're currently using
-        res = samdb.search(base=samdb.get_schema_basedn(), scope=ldb.SCOPE_BASE,
-                           attrs=['objectVersion'])
+            # work out the version of the schema we're currently using
+            res = samdb.search(base=samdb.get_schema_basedn(),
+                               scope=ldb.SCOPE_BASE, attrs=['objectVersion'])
 
-        if len(res) != 1:
-            raise CommandError('Could not determine current schema version')
-        start = int(res[0]['objectVersion'][0]) + 1
+            if len(res) != 1:
+                raise CommandError('Could not determine current schema version')
+            start = int(res[0]['objectVersion'][0]) + 1
+
+            for version in range(start, end + 1):
+                schema_updates.append('Sch%d.ldf' % version)
 
         samdb.transaction_start()
         count = 0
@@ -4071,8 +4083,8 @@ class cmd_domain_schema_upgrade(Command):
 
         try:
             # Apply the schema updates needed to move to the new schema version
-            for version in range(start, end + 1):
-                count += self._apply_update(samdb, 'Sch%d.ldf' % version)
+            for ldif_file in schema_updates:
+                count += self._apply_update(samdb, ldif_file)
 
             if count > 0:
                 samdb.transaction_commit()