summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPetr Spacek <pspacek@redhat.com>2016-04-27 12:49:23 +0200
committerMartin Basti <mbasti@redhat.com>2016-05-30 20:14:32 +0200
commita4da9a23788d9f09f562c12d80353fca42f73441 (patch)
treef45b52e4b0dfe58a22f140bd0d9db7dc91daf63b
parent321a2ba9185e4a21d5b2f9949cd3bec32a1fd60a (diff)
downloadfreeipa-a4da9a23788d9f09f562c12d80353fca42f73441.tar.gz
freeipa-a4da9a23788d9f09f562c12d80353fca42f73441.tar.xz
freeipa-a4da9a23788d9f09f562c12d80353fca42f73441.zip
DNS upgrade: separate backup logic to make it reusable
https://fedorahosted.org/freeipa/ticket/5710 Reviewed-By: Martin Basti <mbasti@redhat.com>
-rw-r--r--ipaserver/install/plugins/dns.py145
1 files changed, 73 insertions, 72 deletions
diff --git a/ipaserver/install/plugins/dns.py b/ipaserver/install/plugins/dns.py
index cb3fad4c1..26b2b84b5 100644
--- a/ipaserver/install/plugins/dns.py
+++ b/ipaserver/install/plugins/dns.py
@@ -33,6 +33,18 @@ register = Registry()
class DNSUpdater(Updater):
+ backup_dir = u'/var/lib/ipa/backup/'
+ # override backup_filename in subclass, it will be mangled by strftime
+ backup_filename = None
+
+ def __init__(self, api):
+ super(DNSUpdater, self).__init__(api)
+ backup_path = u'%s%s' % (self.backup_dir, self.backup_filename)
+ self.backup_path = time.strftime(backup_path)
+ self._ldif_writer = None
+ self._saved_privileges = set() # store privileges only once
+ self.saved_zone_to_privilege = {}
+
def version_update_needed(self, target_version):
"""Test if IPA DNS version is smaller than target version."""
assert isinstance(target_version, int)
@@ -44,6 +56,56 @@ class DNSUpdater(Updater):
# IPA DNS is not configured
return False
+ @property
+ def ldif_writer(self):
+ if not self._ldif_writer:
+ self.log.info('Original zones will be saved in LDIF format in '
+ '%s file' % self.backup_path)
+ self._ldif_writer = LDIFWriter(open(self.backup_path, 'w'))
+ return self._ldif_writer
+
+ def backup_zone(self, zone):
+ """Backup zone object, its records, permissions, and privileges.
+
+ Mapping from zone to privilege (containing zone's permissions)
+ will be stored in saved_zone_to_privilege dict for further usage.
+ """
+ dn = str(zone['dn'])
+ del zone['dn'] # dn shouldn't be as attribute in ldif
+ self.ldif_writer.unparse(dn, zone)
+
+ ldap = self.api.Backend.ldap2
+ if 'managedBy' in zone:
+ permission = ldap.get_entry(DN(zone['managedBy'][0]))
+ self.ldif_writer.unparse(str(permission.dn), dict(permission.raw))
+ for privilege_dn in permission.get('member', []):
+ # privileges can be shared by multiples zones
+ if privilege_dn not in self._saved_privileges:
+ self._saved_privileges.add(privilege_dn)
+ privilege = ldap.get_entry(privilege_dn)
+ self.ldif_writer.unparse(str(privilege.dn),
+ dict(privilege.raw))
+
+ # remember privileges referened by permission
+ if 'member' in permission:
+ self.saved_zone_to_privilege[
+ zone['idnsname'][0]
+ ] = permission['member']
+
+ if 'idnszone' in zone['objectClass']:
+ # raw values are required to store into ldif
+ records = self.api.Command['dnsrecord_find'](zone['idnsname'][0],
+ all=True,
+ raw=True,
+ sizelimit=0)['result']
+ for record in records:
+ if record['idnsname'][0] == u'@':
+ # zone record was saved before
+ continue
+ dn = str(record['dn'])
+ del record['dn']
+ self.ldif_writer.unparse(dn, record)
+
@register()
class update_ipaconfigstring_dnsversion_to_ipadnsversion(Updater):
@@ -206,9 +268,7 @@ class update_master_to_dnsforwardzones(DNSUpdater):
This should be applied only once, and only if original version was lower than 4.0
"""
- backup_dir = u'/var/lib/ipa/backup/'
- backup_filename = u'dns-forward-zones-backup-%Y-%m-%d-%H-%M-%S.ldif'
- backup_path = u'%s%s' % (backup_dir, backup_filename)
+ backup_filename = u'dns-master-to-forward-zones-%Y-%m-%d-%H-%M-%S.ldif'
def execute(self, **options):
ldap = self.api.Backend.ldap2
@@ -260,77 +320,18 @@ class update_master_to_dnsforwardzones(DNSUpdater):
zones_to_transform.append(zone)
if zones_to_transform:
- # add time to filename
- self.backup_path = time.strftime(self.backup_path)
-
- # DNs of privileges which contain dns managed permissions
- privileges_to_ldif = set() # store priviledges only once
- zone_to_privileges = {} # zone: [privileges cn]
-
self.log.info('Zones with specified forwarders with policy different'
' than none will be transformed to forward zones.')
- self.log.info('Original zones will be saved in LDIF format in '
- '%s file' % self.backup_path)
- try:
-
- with open(self.backup_path, 'w') as f:
- writer = LDIFWriter(f)
- for zone in zones_to_transform:
- # save backup to ldif
- try:
-
- dn = str(zone['dn'])
- del zone['dn'] # dn shouldn't be as attribute in ldif
- writer.unparse(dn, zone)
-
- if 'managedBy' in zone:
- entry = ldap.get_entry(DN(zone['managedBy'][0]))
- for privilege_member_dn in entry.get('member', []):
- privileges_to_ldif.add(privilege_member_dn)
- writer.unparse(str(entry.dn), dict(entry.raw))
-
- # privileges where permission is used
- if entry.get('member'):
- zone_to_privileges[zone['idnsname'][0]] = entry['member']
-
- # raw values are required to store into ldif
- records = self.api.Command['dnsrecord_find'](
- zone['idnsname'][0],
- all=True,
- raw=True,
- sizelimit=0)['result']
- for record in records:
- if record['idnsname'][0] == u'@':
- # zone record was saved before
- continue
- dn = str(record['dn'])
- del record['dn']
- writer.unparse(dn, record)
-
- except Exception as e:
- self.log.error('Unable to backup zone %s' %
- zone['idnsname'][0])
- self.log.error(traceback.format_exc())
- return False, []
-
- for privilege_dn in privileges_to_ldif:
- try:
- entry = ldap.get_entry(privilege_dn)
- writer.unparse(str(entry.dn), dict(entry.raw))
- except Exception as e:
- self.log.error('Unable to backup privilege %s' %
- privilege_dn)
- self.log.error(traceback.format_exc())
- return False, []
-
- f.close()
- except Exception:
- self.log.error('Unable to create backup file')
- self.log.error(traceback.format_exc())
- return False, []
-
# update
for zone in zones_to_transform:
+ try:
+ self.backup_zone(zone)
+ except Exception:
+ self.log.error('Unable to create backup for zone, '
+ 'terminating zone upgrade')
+ self.log.error(traceback.format_exc())
+ return False, []
+
# delete master zone
try:
self.api.Command['dnszone_del'](zone['idnsname'])
@@ -374,9 +375,9 @@ class update_master_to_dnsforwardzones(DNSUpdater):
continue
else:
- if zone['idnsname'][0] in zone_to_privileges:
+ if zone['idnsname'][0] in self.saved_zone_to_privilege:
privileges = [
- dn[0].value for dn in zone_to_privileges[zone['idnsname'][0]]
+ dn[0].value for dn in self.saved_zone_to_privilege[zone['idnsname'][0]]
]
try:
self.api.Command['permission_add_member'](perm_name,