summaryrefslogtreecommitdiffstats
path: root/server/upgrade
diff options
context:
space:
mode:
authorJakub Hrozek <jhrozek@redhat.com>2009-11-19 19:40:12 +0100
committerStephen Gallagher <sgallagh@redhat.com>2009-11-20 11:18:48 -0500
commit78988f8fbc3a4289d41b09dd099df860d0b1427e (patch)
tree4c12110307fa558ed99869df452f555bfe23801b /server/upgrade
parent287c0086512f806ae1800e144c0b0680867928ba (diff)
downloadsssd-78988f8fbc3a4289d41b09dd099df860d0b1427e.tar.gz
sssd-78988f8fbc3a4289d41b09dd099df860d0b1427e.tar.xz
sssd-78988f8fbc3a4289d41b09dd099df860d0b1427e.zip
Change the upgrade script to use ipachangeconf
With this patch, the upgrade script we use for changing the config files is able to keep ordering and comments. Fixes: #249
Diffstat (limited to 'server/upgrade')
-rw-r--r--server/upgrade/upgrade_config.py407
1 files changed, 0 insertions, 407 deletions
diff --git a/server/upgrade/upgrade_config.py b/server/upgrade/upgrade_config.py
deleted file mode 100644
index 213bb730c..000000000
--- a/server/upgrade/upgrade_config.py
+++ /dev/null
@@ -1,407 +0,0 @@
-#!/usr/bin/python
-#coding=utf-8
-
-# SSSD
-#
-# upgrade_config.py
-#
-# Copyright (C) Jakub Hrozek <jhrozek@redhat.com> 2009
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-import os
-import sys
-import shutil
-import traceback
-import copy
-from ConfigParser import RawConfigParser
-from ConfigParser import NoOptionError
-from optparse import OptionParser
-
-class SSSDConfigParser(RawConfigParser):
- def raw_set(self, section, option):
- " set without interpolation "
- pass
-
- def raw_get(self, section, option):
- " get without interpolation "
- return self._sections[section].get(option)
-
- def _write_section(self, section, fp):
- fp.write("[%s]\n" % section)
- for (key, value) in sorted(self._sections[section].items()):
- if key != "__name__":
- fp.write("%s = %s\n" %
- (key, str(value).replace('\n', '\n\t')))
- fp.write("\n")
-
- def write(self, fp):
- """
- SSSD Config file uses a logical order of sections
- ConfigParser does not allow sorting the sections, so
- we hackishly sort them here..
- """
- # Write SSSD first
- if "sssd" in self._sections:
- self._write_section("sssd", fp)
- if (self.has_option('sssd', 'domains')):
- active_domains = [s.strip() for s in self.get('sssd','domains').split(',')]
- else:
- #There were no active domains configured
- active_domains = []
- del self._sections["sssd"]
- # Write the other services
- for service in [ s for s in self._sections if not s.startswith('domain/') ]:
- self._write_section(service, fp)
- del self._sections[service]
-
- # Write the domains in the order that is specified in domains =
- for dom in active_domains:
- self._write_section('domain/%s' % dom, fp)
- del self._sections['domain/%s' % dom]
-
- # Write inactive domains
- for section in sorted(self._sections):
- self._write_section(section, fp)
-
-class SSSDConfigFile(object):
- def __init__(self, file_name):
- self.file_name = file_name
- self._config = SSSDConfigParser()
- self._new_config = SSSDConfigParser()
- self._config.read(file_name)
-
- def get_version(self):
- " Guess if we are looking at v1 config file "
- if not self._config.has_section('sssd'):
- return 1
- if not self._config.has_option('sssd', 'config_file_version'):
- return 1
- return self._config.getint('sssd', 'config_file_version')
-
- def _backup_file(self):
- " Copy the file we operate on to a backup location "
- shutil.copy(self.file_name, self.file_name+".bak")
-
- # make sure we don't leak data, force permissions on the backup
- os.chmod(self.file_name+".bak", 0600)
-
- def _migrate_if_exists(self, to_section, to_option, from_section, from_option):
- """
- Move value of parameter from one section to another, renaming the parameter
- """
- if self._config.has_section(from_section) and \
- self._config.has_option(from_section, from_option):
- self._new_config.set(to_section, to_option,
- self._config.get(from_section, from_option))
-
- def _migrate_kw(self, to_section, from_section, new_old_dict):
- """
- Move value of parameter from one section to another according to
- mapping in ``new_old_dict``
- """
- for new, old in new_old_dict.items():
- self._migrate_if_exists(to_section, new, from_section, old)
-
- def _migrate_enumerate(self, to_section, from_section):
- " Enumerate was special as it turned into bool from (0,1,2,3) enum "
- if self._config.has_section(from_section) and \
- self._config.has_option(from_section, 'enumerate'):
- enumvalue = self._config.get(from_section, 'enumerate')
- if enumvalue.upper() in ['TRUE', 'FALSE']:
- self._new_config.set(to_section, 'enumerate', enumvalue)
- else:
- try:
- enumvalue = int(enumvalue)
- except ValueError:
- raise ValueError('Cannot convert value %s in domain %s' % (enumvalue, from_section))
-
- if enumvalue == 0:
- self._new_config.set(to_section, 'enumerate', 'FALSE')
- elif enumvalue > 0:
- self._new_config.set(to_section, 'enumerate', 'TRUE')
- else:
- raise ValueError('Cannot convert value %s in domain %s' % (enumvalue, from_section))
-
- def _migrate_domain(self, domain):
- new_domsec = 'domain/%s' % domain
- old_domsec = 'domains/%s' % domain
- self._new_config.add_section(new_domsec)
-
- # Generic options - new:old
- generic_kw = { 'min_id' : 'minID',
- 'max_id': 'maxID',
- 'timeout': 'timeout',
- 'magic_private_groups' : 'magicPrivateGroups',
- 'cache_credentials' : 'cache-credentials',
- 'id_provider' : 'provider',
- 'auth_provider' : 'auth-module',
- 'access_provider' : 'access-module',
- 'chpass_provider' : 'chpass-module',
- 'use_fully_qualified_names' : 'useFullyQualifiedNames',
- }
- # Proxy options
- proxy_kw = { 'proxy_pam_target' : 'pam-target',
- 'proxy_lib_name' : 'libName',
- }
- # LDAP options - new:old
- ldap_kw = { 'ldap_uri' : 'ldapUri',
- 'ldap_schema' : 'ldapSchema',
- 'ldap_default_bind_dn' : 'defaultBindDn',
- 'ldap_default_authtok_type' : 'defaultAuthtokType',
- 'ldap_default_authtok' : 'defaultAuthtok',
- 'ldap_user_search_base' : 'userSearchBase',
- 'ldap_user_search_scope' : 'userSearchScope',
- 'ldap_user_search_filter' : 'userSearchFilter',
- 'ldap_user_object_class' : 'userObjectClass',
- 'ldap_user_name' : 'userName',
- 'ldap_user_pwd' : 'userPassword',
- 'ldap_user_uid_number' : 'userUidNumber',
- 'ldap_user_gid_number' : 'userGidNumber',
- 'ldap_user_gecos' : 'userGecos',
- 'ldap_user_home_directory' : 'userHomeDirectory',
- 'ldap_user_shell' : 'userShell',
- 'ldap_user_uuid' : 'userUUID',
- 'ldap_user_principal' : 'userPrincipal',
- 'ldap_force_upper_case_realm' : 'force_upper_case_realm',
- 'ldap_user_fullname' : 'userFullname',
- 'ldap_user_member_of' : 'userMemberOf',
- 'ldap_user_modify_timestamp' : 'modifyTimestamp',
- 'ldap_group_search_base' : 'groupSearchBase',
- 'ldap_group_search_scope' : 'groupSearchScope',
- 'ldap_group_search_filter' : 'groupSearchFilter',
- 'ldap_group_object_class' : 'groupObjectClass',
- 'ldap_group_name' : 'groupName',
- 'ldap_group_pwd' : 'userPassword',
- 'ldap_group_gid_number' : 'groupGidNumber',
- 'ldap_group_member' : 'groupMember',
- 'ldap_group_uuid' : 'groupUUID',
- 'ldap_group_modify_timestamp' : 'modifyTimestamp',
- 'ldap_network_timeout' : 'network_timeout',
- 'ldap_offline_timeout' : 'offline_timeout',
- 'ldap_enumeration_refresh_timeout' : 'enumeration_refresh_timeout',
- 'ldap_stale_time' : 'stale_time',
- 'ldap_opt_timeout' : 'opt_timeout',
- 'ldap_tls_reqcert' : 'tls_reqcert',
- }
- krb5_kw = { 'krb5_kdcip' : 'krb5KDCIP',
- 'krb5_realm' : 'krb5REALM',
- 'krb5_try_simple_upn' : 'krb5try_simple_upn',
- 'krb5_changepw_principal' : 'krb5changepw_principle',
- 'krb5_ccachedir' : 'krb5ccache_dir',
- 'krb5_auth_timeout' : 'krb5auth_timeout',
- 'krb5_ccname_template' : 'krb5ccname_template',
- }
- user_defaults_kw = { 'default_shell' : 'defaultShell',
- 'base_directory' : 'baseDirectory',
- }
-
- self._migrate_enumerate(new_domsec, old_domsec)
- self._migrate_kw(new_domsec, old_domsec, generic_kw)
- self._migrate_kw(new_domsec, old_domsec, proxy_kw)
- self._migrate_kw(new_domsec, old_domsec, ldap_kw)
- self._migrate_kw(new_domsec, old_domsec, krb5_kw)
-
- # configuration files before 0.5.0 did not enforce provider= in local domains
- # it did special-case by domain name (LOCAL)
- try:
- prv = self._new_config.get(new_domsec, 'id_provider')
- except NoOptionError:
- if old_domsec == 'domains/LOCAL':
- prv = 'local'
- self._new_config.set(new_domsec, 'id_provider', prv)
-
- # if domain was local, update with parameters from [user_defaults]
- if prv == 'local':
- self._migrate_kw(new_domsec, 'user_defaults', user_defaults_kw)
-
- def _migrate_domains(self):
- for domain in [ s.replace('domains/','') for s in self._config.sections() if s.startswith("domains/") ]:
- domain = domain.strip()
- self._migrate_domain(domain)
-
- def _remove_dp(self):
- # If data provider is in the list of active services, remove it
- if self._new_config.has_option('sssd', 'services'):
- services = [ srv.strip() for srv in self._new_config.get('sssd', 'services').split(',') ]
- if 'dp' in services:
- services.remove('dp')
-
- self._new_config.set('sssd', 'services', ", ".join([srv for srv in services]))
-
- # also remove the [dp] section
- self._new_config.remove_section('dp')
-
- def _do_v2_changes(self):
- # the changes themselves
- self._remove_dp()
-
- def v2_changes(self, out_file_name, backup=True):
- """
- Check for needed changes in V2 format and write the result into
- ``out_file_name```.
- """
- # basically a wrapper around _do_v2_changes
- self._new_config = copy.deepcopy(self._config)
-
- if backup:
- self._backup_file()
-
- self._do_v2_changes()
-
- # all done, open the file for writing
- of = open(out_file_name, "wb")
-
- # make sure it has the right permissions too
- os.chmod(out_file_name, 0600)
- self._new_config.write(of)
-
- def upgrade_v2(self, out_file_name, backup=True):
- """
- Upgrade the config file to V2 format and write the result into
- ``out_file_name```.
- """
- if backup:
- self._backup_file()
-
- # [service] - options common to all services, no section as in v1
- service_kw = { 'reconnection_retries' : 'reconnection_retries',
- 'debug_level' : 'debug-level',
- 'debug_timestamps' : 'debug-timestamps',
- 'command' : 'command',
- 'timeout' : 'timeout',
- }
-
- # [sssd] - monitor service
- self._new_config.add_section('sssd')
- self._new_config.set('sssd', 'config_file_version', '2')
- self._migrate_if_exists('sssd', 'domains',
- 'domains', 'domains')
- self._migrate_if_exists('sssd', 'services',
- 'services', 'activeServices')
- self._migrate_if_exists('sssd', 'sbus_timeout',
- 'services/monitor', 'sbusTimeout')
- self._migrate_if_exists('sssd', 're_expression',
- 'names', 're-expression')
- self._migrate_if_exists('sssd', 're_expression',
- 'names', 'full-name-format')
- self._migrate_kw('sssd', 'services', service_kw)
- self._migrate_kw('sssd', 'services/monitor', service_kw)
-
- # [nss] - Name service
- self._new_config.add_section('nss')
- nss_kw = { 'enum_cache_timeout' : 'EnumCacheTimeout',
- 'entry_cache_timeout' : 'EntryCacheTimeout',
- 'entry_cache_nowait_timeout' : 'EntryCacheNoWaitRefreshTimeout',
- 'entry_negative_timeout ' : 'EntryNegativeTimeout',
- 'filter_users' : 'filterUsers',
- 'filter_groups' : 'filterGroups',
- 'filter_users_in_groups' : 'filterUsersInGroups',
- }
- nss_kw.update(service_kw)
- self._migrate_kw('nss', 'services', service_kw)
- self._migrate_kw('nss', 'services/nss', nss_kw)
-
- # [pam] - Authentication service
- self._new_config.add_section('pam')
- pam_kw = {}
- pam_kw.update(service_kw)
- self._migrate_kw('pam', 'services', service_kw)
- self._migrate_kw('pam', 'services/pam', pam_kw)
-
- # Migrate domains
- self._migrate_domains()
-
- # Perform neccessary changes
- self._do_v2_changes()
-
- # all done, open the file for writing
- of = open(out_file_name, "wb")
-
- # make sure it has the right permissions too
- os.chmod(out_file_name, 0600)
-
- self._new_config.write(of)
-
-def parse_options():
- parser = OptionParser()
- parser.add_option("-f", "--file",
- dest="filename", default="/etc/sssd/sssd.conf",
- help="Set input file to FILE", metavar="FILE")
- parser.add_option("-o", "--outfile",
- dest="outfile", default=None,
- help="Set output file to OUTFILE", metavar="OUTFILE")
- parser.add_option("", "--no-backup", action="store_false",
- dest="backup", default=True,
- help="""Do not provide backup file after conversion.
-The script copies the original file with the suffix .bak
-by default""")
- parser.add_option("-v", "--verbose", action="store_true",
- dest="verbose", default=False,
- help="Be verbose")
- (options, args) = parser.parse_args()
- if len(args) > 0:
- print >>sys.stderr, "Stray arguments: %s" % ' '.join([a for a in args])
- return None
-
- # do the conversion in place by default
- if not options.outfile:
- options.outfile = options.filename
-
- return options
-
-def verbose(msg, verbose):
- if verbose:
- print msg
-
-def main():
- options = parse_options()
- if not options:
- print >>sys.stderr, "Cannot parse options"
- return 1
-
- try:
- config = SSSDConfigFile(options.filename)
- except SSSDConfigParser.ParsingError:
- print >>sys.stderr, "Cannot parse config file %s" % options.filename
- return 1
-
- # make sure we keep strict settings when creating new files
- os.umask(0077)
-
- version = config.get_version()
- if version == 2:
- try:
- config.v2_changes(options.outfile, options.backup)
- except Exception, e:
- print "ERROR: %s" % e
- verbose(traceback.format_exc(), options.verbose)
- return 1
- elif version == 1:
- try:
- config.upgrade_v2(options.outfile, options.backup)
- except Exception, e:
- print "ERROR: %s" % e
- verbose(traceback.format_exc(), options.verbose)
- return 1
- else:
- print >>sys.stderr, "Can only upgrade from v1 to v2, file %s looks like version %d" % (options.filename, config.get_version())
- return 1
-
- return 0
-
-if __name__ == "__main__":
- ret = main()
- sys.exit(ret)
-