mirror of
https://github.com/samba-team/samba.git
synced 2025-01-20 14:03:59 +03:00
gpo: Add a --generalize to the backup command
This normally prints out the entities in DTD form to be given to the restore command with --entities. Specifying --entities during the backup conveniently writes these entities to a file. Generalizing occurs after the standard backup on the XML files, which will then re-write the XML file. There are a number of files which can be further handled, including many of the preferences XML files. This will require more annotation and parsing. Signed-off-by: Garming Sam <garming@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abartlet@samba.org>
This commit is contained in:
parent
3ff695fd36
commit
07de156598
@ -48,7 +48,7 @@ import uuid
|
|||||||
from samba.ntacls import dsacl2fsacl
|
from samba.ntacls import dsacl2fsacl
|
||||||
from samba.dcerpc import nbt
|
from samba.dcerpc import nbt
|
||||||
from samba.net import Net
|
from samba.net import Net
|
||||||
from samba.gp_parse import GPParser, GPNoParserException
|
from samba.gp_parse import GPParser, GPNoParserException, GPGeneralizeException
|
||||||
from samba.gp_parse.gp_pol import GPPolParser
|
from samba.gp_parse.gp_pol import GPPolParser
|
||||||
from samba.gp_parse.gp_ini import (
|
from samba.gp_parse.gp_ini import (
|
||||||
GPIniParser,
|
GPIniParser,
|
||||||
@ -965,10 +965,15 @@ class cmd_backup(Command):
|
|||||||
|
|
||||||
takes_options = [
|
takes_options = [
|
||||||
Option("-H", help="LDB URL for database or target server", type=str),
|
Option("-H", help="LDB URL for database or target server", type=str),
|
||||||
Option("--tmpdir", help="Temporary directory for copying policy files", type=str)
|
Option("--tmpdir", help="Temporary directory for copying policy files", type=str),
|
||||||
|
Option("--generalize", help="Generalize XML entities to restore",
|
||||||
|
default=False, action='store_true'),
|
||||||
|
Option("--entities", help="File to export defining XML entities for the restore",
|
||||||
|
dest='ent_file', type=str)
|
||||||
]
|
]
|
||||||
|
|
||||||
def run(self, gpo, H=None, tmpdir=None, sambaopts=None, credopts=None, versionopts=None):
|
def run(self, gpo, H=None, tmpdir=None, generalize=False, sambaopts=None,
|
||||||
|
credopts=None, versionopts=None, ent_file=None):
|
||||||
|
|
||||||
self.lp = sambaopts.get_loadparm()
|
self.lp = sambaopts.get_loadparm()
|
||||||
self.creds = credopts.get_credentials(self.lp, fallback_machine=True)
|
self.creds = credopts.get_credentials(self.lp, fallback_machine=True)
|
||||||
@ -1020,8 +1025,79 @@ class cmd_backup(Command):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
# FIXME: Catch more specific exception
|
# FIXME: Catch more specific exception
|
||||||
raise CommandError("Error copying GPO from DC", e)
|
raise CommandError("Error copying GPO from DC", e)
|
||||||
|
|
||||||
self.outf.write('GPO copied to %s\n' % gpodir)
|
self.outf.write('GPO copied to %s\n' % gpodir)
|
||||||
|
|
||||||
|
if generalize:
|
||||||
|
self.outf.write('\nAttempting to generalize XML entities:\n')
|
||||||
|
entities = cmd_backup.generalize_xml_entities(self.outf, gpodir,
|
||||||
|
gpodir)
|
||||||
|
import operator
|
||||||
|
ents = ''
|
||||||
|
for ent in sorted(entities.items(), key=operator.itemgetter(1)):
|
||||||
|
ents += '<!ENTITY {} "{}">\n'.format(ent[1].strip('&;'), ent[0])
|
||||||
|
|
||||||
|
if ent_file:
|
||||||
|
with open(ent_file, 'w') as f:
|
||||||
|
f.write(ents)
|
||||||
|
self.outf.write('Entities successfully written to %s\n' %
|
||||||
|
ent_file)
|
||||||
|
else:
|
||||||
|
self.outf.write('\nEntities:\n')
|
||||||
|
self.outf.write(ents)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def generalize_xml_entities(outf, sourcedir, targetdir):
|
||||||
|
entities = {}
|
||||||
|
|
||||||
|
if not os.path.exists(targetdir):
|
||||||
|
os.mkdir(targetdir)
|
||||||
|
|
||||||
|
l_dirs = [ sourcedir ]
|
||||||
|
r_dirs = [ targetdir ]
|
||||||
|
while l_dirs:
|
||||||
|
l_dir = l_dirs.pop()
|
||||||
|
r_dir = r_dirs.pop()
|
||||||
|
|
||||||
|
dirlist = os.listdir(l_dir)
|
||||||
|
dirlist.sort()
|
||||||
|
for e in dirlist:
|
||||||
|
l_name = os.path.join(l_dir, e)
|
||||||
|
r_name = os.path.join(r_dir, e)
|
||||||
|
|
||||||
|
if os.path.isdir(l_name):
|
||||||
|
l_dirs.append(l_name)
|
||||||
|
r_dirs.append(r_name)
|
||||||
|
if not os.path.exists(r_name):
|
||||||
|
os.mkdir(r_name)
|
||||||
|
else:
|
||||||
|
if l_name.endswith('.xml'):
|
||||||
|
# Restore the xml file if possible
|
||||||
|
|
||||||
|
# Get the filename to find the parser
|
||||||
|
to_parse = os.path.basename(l_name)[:-4]
|
||||||
|
|
||||||
|
parser = find_parser(to_parse)
|
||||||
|
try:
|
||||||
|
with open(l_name, 'r') as ltemp:
|
||||||
|
data = ltemp.read()
|
||||||
|
|
||||||
|
concrete_xml = ET.fromstring(data)
|
||||||
|
found_entities = parser.generalize_xml(concrete_xml, r_name, entities)
|
||||||
|
except GPGeneralizeException:
|
||||||
|
outf.write('SKIPPING: Generalizing failed for %s\n' % to_parse)
|
||||||
|
|
||||||
|
else:
|
||||||
|
# No need to generalize non-xml files.
|
||||||
|
#
|
||||||
|
# TODO This could be improved with xml files stored in
|
||||||
|
# the renamed backup file (with custom extension) by
|
||||||
|
# inlining them into the exported backups.
|
||||||
|
if not os.path.samefile(l_name, r_name):
|
||||||
|
shutil.copy2(l_name, r_name)
|
||||||
|
|
||||||
|
return entities
|
||||||
|
|
||||||
|
|
||||||
class cmd_create(Command):
|
class cmd_create(Command):
|
||||||
"""Create an empty GPO."""
|
"""Create an empty GPO."""
|
||||||
@ -1213,6 +1289,7 @@ class cmd_restore(cmd_create):
|
|||||||
r_dir = r_dirs.pop()
|
r_dir = r_dirs.pop()
|
||||||
|
|
||||||
dirlist = os.listdir(l_dir)
|
dirlist = os.listdir(l_dir)
|
||||||
|
dirlist.sort()
|
||||||
for e in dirlist:
|
for e in dirlist:
|
||||||
l_name = os.path.join(l_dir, e)
|
l_name = os.path.join(l_dir, e)
|
||||||
r_name = os.path.join(r_dir, e)
|
r_name = os.path.join(r_dir, e)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user