diff options
author | Jan Cholasta <jcholast@redhat.com> | 2015-06-09 11:42:50 +0000 |
---|---|---|
committer | Jan Cholasta <jcholast@redhat.com> | 2015-06-10 07:29:58 +0000 |
commit | 46cbe26b51f7eeeeac8f24351d165c50d415326f (patch) | |
tree | c13eba786447cd1061b27930e516f3bb8a41026c | |
parent | 6f1ae05d8dac1f7c1ff499acd5b401f316618f4a (diff) | |
download | freeipa-46cbe26b51f7eeeeac8f24351d165c50d415326f.tar.gz freeipa-46cbe26b51f7eeeeac8f24351d165c50d415326f.tar.xz freeipa-46cbe26b51f7eeeeac8f24351d165c50d415326f.zip |
install: Migrate ipa-replica-install to the install framework
https://fedorahosted.org/freeipa/ticket/4468
Reviewed-By: David Kupka <dkupka@redhat.com>
-rwxr-xr-x | install/tools/ipa-replica-install | 151 | ||||
-rw-r--r-- | ipaserver/install/server/__init__.py | 3 | ||||
-rw-r--r-- | ipaserver/install/server/replicainstall.py | 322 |
3 files changed, 275 insertions, 201 deletions
diff --git a/install/tools/ipa-replica-install b/install/tools/ipa-replica-install index 791a27292..10a10827e 100755 --- a/install/tools/ipa-replica-install +++ b/install/tools/ipa-replica-install @@ -18,148 +18,19 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. # -import sys -import os -from optparse import OptionGroup - -from ipapython import ipautil -from ipaserver.install import installutils -from ipaserver.install import server -from ipapython import version -from ipapython.config import IPAOptionParser -from ipapython.ipa_log_manager import root_logger, standard_logging_setup -from ipapython.dn import DN +from ipapython.install import cli from ipaplatform.paths import paths +from ipaserver.install.server import Replica -log_file_name = paths.IPAREPLICA_INSTALL_LOG -DIRMAN_DN = DN(('cn', 'directory manager')) -REPLICA_INFO_TOP_DIR = None - - -def parse_options(): - usage = "%prog [options] REPLICA_FILE" - parser = IPAOptionParser(usage=usage, version=version.VERSION) - - basic_group = OptionGroup(parser, "basic options") - basic_group.add_option("--setup-ca", dest="setup_ca", action="store_true", - default=False, help="configure a dogtag CA") - basic_group.add_option("--setup-kra", dest="setup_kra", action="store_true", - default=False, help="configure a dogtag KRA") - basic_group.add_option("--ip-address", dest="ip_addresses", - type="ip", ip_local=True, action="append", default=[], - help="Replica server IP Address. This option can be used multiple times", metavar="IP_ADDRESS") - basic_group.add_option("-p", "--password", dest="password", sensitive=True, - help="Directory Manager (existing master) password") - basic_group.add_option("-w", "--admin-password", dest="admin_password", sensitive=True, - help="Admin user Kerberos password used for connection check") - basic_group.add_option("--mkhomedir", - dest="mkhomedir", - action="store_true", - default=False, - help="create home directories for users " - "on their first login") - basic_group.add_option("-N", "--no-ntp", dest="conf_ntp", action="store_false", - help="do not configure ntp", default=True) - basic_group.add_option("--no-ui-redirect", dest="ui_redirect", action="store_false", - default=True, help="Do not automatically redirect to the Web UI") - basic_group.add_option("--ssh-trust-dns", dest="trust_sshfp", default=False, action="store_true", - help="configure OpenSSH client to trust DNS SSHFP records") - basic_group.add_option("--no-ssh", dest="conf_ssh", default=True, action="store_false", - help="do not configure OpenSSH client") - basic_group.add_option("--no-sshd", dest="conf_sshd", default=True, action="store_false", - help="do not configure OpenSSH server") - basic_group.add_option("--skip-conncheck", dest="skip_conncheck", action="store_true", - default=False, help="skip connection check to remote master") - basic_group.add_option("-d", "--debug", dest="debug", action="store_true", - default=False, help="gather extra debugging information") - basic_group.add_option("-U", "--unattended", dest="unattended", action="store_true", - default=False, help="unattended installation never prompts the user") - parser.add_option_group(basic_group) - - cert_group = OptionGroup(parser, "certificate system options") - cert_group.add_option("--no-pkinit", dest="setup_pkinit", action="store_false", - default=True, help="disables pkinit setup steps") - cert_group.add_option("--skip-schema-check", dest="skip_schema_check", action="store_true", - default=False, help="skip check for updated CA DS schema on the remote master") - parser.add_option_group(cert_group) - - dns_group = OptionGroup(parser, "DNS options") - dns_group.add_option("--setup-dns", dest="setup_dns", action="store_true", - default=False, help="configure bind with our zone") - dns_group.add_option("--forwarder", dest="forwarders", action="append", - type="ip", help="Add a DNS forwarder. This option can be used multiple times") - dns_group.add_option("--no-forwarders", dest="no_forwarders", action="store_true", - default=False, help="Do not add any DNS forwarders, use root servers instead") - dns_group.add_option("--reverse-zone", dest="reverse_zones", default=[], - action="append", help="The reverse DNS zone to use. This option can be used multiple times", - metavar="REVERSE_ZONE") - dns_group.add_option("--no-reverse", dest="no_reverse", action="store_true", - default=False, help="Do not create new reverse DNS zone") - dns_group.add_option("--no-dnssec-validation", dest="no_dnssec_validation", action="store_true", - default=False, help="Disable DNSSEC validation") - dns_group.add_option("--no-host-dns", dest="no_host_dns", action="store_true", - default=False, - help="Do not use DNS for hostname lookup during installation") - dns_group.add_option("--no-dns-sshfp", dest="create_sshfp", default=True, action="store_false", - help="do not automatically create DNS SSHFP records") - parser.add_option_group(dns_group) - - options, args = parser.parse_args() - safe_options = parser.get_safe_opts(options) - - if len(args) != 1: - parser.error("you must provide a file generated by ipa-replica-prepare") - - if not options.setup_dns: - if options.forwarders: - parser.error("You cannot specify a --forwarder option without the --setup-dns option") - if options.no_forwarders: - parser.error("You cannot specify a --no-forwarders option without the --setup-dns option") - if options.reverse_zones: - parser.error("You cannot specify a --reverse-zone option without the --setup-dns option") - if options.no_reverse: - parser.error("You cannot specify a --no-reverse option without the --setup-dns option") - if options.no_dnssec_validation: - parser.error("You cannot specify a --no-dnssec-validation option without the --setup-dns option") - elif options.forwarders and options.no_forwarders: - parser.error("You cannot specify a --forwarder option together with --no-forwarders") - elif not options.forwarders and not options.no_forwarders: - parser.error("You must specify at least one --forwarder option or --no-forwarders option") - elif options.reverse_zones and options.no_reverse: - parser.error("You cannot specify a --reverse-zone option together with --no-reverse") - - options.external_ca = None - options.external_cert_files = None - - options.zonemgr = None - options.dnssec_master = False - - return safe_options, options, args[0] - - -def main(): - safe_options, options, filename = parse_options() - - if os.geteuid() != 0: - sys.exit("\nYou must be root to run this script.\n") - - standard_logging_setup(log_file_name, debug=options.debug) - root_logger.debug('%s was invoked with argument "%s" and options: %s' % (sys.argv[0], filename, safe_options)) - root_logger.debug('IPA version %s' % version.VENDOR_VERSION) - - if not ipautil.file_exists(filename): - sys.exit("Replica file %s does not exist" % filename) - - server.replica_install_check(filename, options) - server.replica_install(filename, options) +ReplicaInstall = cli.install_tool( + Replica, + command_name='ipa-replica-install', + positional_arguments='replica_file', + usage='%prog [options] REPLICA_FILE', + log_file_name=paths.IPAREPLICA_INSTALL_LOG, + debug_option=True, +) -fail_message = ''' -Your system may be partly configured. -Run /usr/sbin/ipa-server-install --uninstall to clean up. -''' -if __name__ == '__main__': - installutils.run_script(main, log_file_name=log_file_name, - operation_name='ipa-replica-install', - fail_message=fail_message) +ReplicaInstall.run_cli() diff --git a/ipaserver/install/server/__init__.py b/ipaserver/install/server/__init__.py index a6db965ca..da2ceec9c 100644 --- a/ipaserver/install/server/__init__.py +++ b/ipaserver/install/server/__init__.py @@ -3,7 +3,6 @@ # from .install import Server +from .replicainstall import Replica -from .replicainstall import install_check as replica_install_check -from .replicainstall import install as replica_install from .upgrade import upgrade_check, upgrade diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py index 149d6b4f0..945511709 100644 --- a/ipaserver/install/server/replicainstall.py +++ b/ipaserver/install/server/replicainstall.py @@ -14,6 +14,9 @@ import tempfile from ipapython import dogtag, ipautil, sysrestore from ipapython.dn import DN +from ipapython.install import common, core +from ipapython.install.common import step +from ipapython.install.core import Knob from ipapython.ipa_log_manager import root_logger from ipaplatform import services from ipaplatform.tasks import tasks @@ -28,7 +31,6 @@ from ipaserver.install.replication import ( ReplicationManager, replica_conn_check) DIRMAN_DN = DN(('cn', 'directory manager')) -REPLICA_INFO_TOP_DIR = None def get_dirman_password(): @@ -162,7 +164,7 @@ def install_dns_records(config, options, remote_api): config.realm_name, config.domain_name, reverse_zone, - options.conf_ntp, + not options.no_ntp, options.setup_ca) except errors.NotFound, e: root_logger.debug('Replica DNS records could not be added ' @@ -276,60 +278,38 @@ def check_dns_resolution(host_name, dns_servers): return no_errors -def remove_replica_info_dir(): +def remove_replica_info_dir(installer): # always try to remove decrypted replica file try: - if REPLICA_INFO_TOP_DIR: - shutil.rmtree(REPLICA_INFO_TOP_DIR) + if installer._top_dir is not None: + shutil.rmtree(installer._top_dir) except OSError: pass -def init_private_ccache(): - global original_ccache - global temp_ccache - - (desc, temp_ccache) = tempfile.mkstemp(prefix='krbcc') - os.close(desc) - - original_ccache = os.environ.get('KRB5CCNAME') - - os.environ['KRB5CCNAME'] = temp_ccache - - -def destroy_private_ccache(): - global original_ccache - global temp_ccache - - if original_ccache is not None: - os.environ['KRB5CCNAME'] = original_ccache - else: - os.environ.pop('KRB5CCNAME', None) - - if os.path.exists(temp_ccache): - os.remove(temp_ccache) - - def common_cleanup(func): - def decorated(*args, **kwargs): + def decorated(installer): try: try: - func(*args, **kwargs) + func(installer) except BaseException: - destroy_private_ccache() - remove_replica_info_dir() + remove_replica_info_dir(installer) raise except KeyboardInterrupt: sys.exit(1) + except Exception: + print( + "Your system may be partly configured.\n" + "Run /usr/sbin/ipa-server-install --uninstall to clean up.\n") + raise return decorated @common_cleanup -def install_check(filename, options): - global config - - init_private_ccache() +def install_check(installer): + options = installer + filename = installer.replica_file tasks.check_selinux_status() @@ -339,10 +319,8 @@ def install_check(filename, options): "Please uninstall it first before configuring the replica, " "using 'ipa-client-install --uninstall'.") - global sstore sstore = sysrestore.StateFile(paths.SYSRESTORE) - global fstore fstore = sysrestore.FileStore(paths.SYSRESTORE) # Check to see if httpd is already configured to listen on 443 @@ -351,7 +329,7 @@ def install_check(filename, options): check_dirsrv() - if options.conf_ntp: + if not options.no_ntp: try: ipaclient.ntpconf.check_timedate_services() except ipaclient.ntpconf.NTPConflictingService, e: @@ -373,8 +351,7 @@ def install_check(filename, options): sys.exit("Directory Manager password required") config = create_replica_config(dirman_password, filename, options) - global REPLICA_INFO_TOP_DIR - REPLICA_INFO_TOP_DIR = config.top_dir + installer._top_dir = config.top_dir config.setup_ca = options.setup_ca config.setup_kra = options.setup_kra @@ -398,7 +375,7 @@ def install_check(filename, options): dns.install_check(False, True, options, config.host_name) else: installutils.get_server_ip_address(config.host_name, fstore, - options.unattended, False, + not installer.interactive, False, options.ip_addresses) # check connection @@ -407,18 +384,22 @@ def install_check(filename, options): config.master_host_name, config.host_name, config.realm_name, options.setup_ca, config.ca_ds_port, options.admin_password) - # Automatically disable pkinit w/ dogtag until that is supported - options.setup_pkinit = False - cafile = config.dir + "/ca.crt" if not ipautil.file_exists(cafile): raise RuntimeError("CA cert file is not available. Please run " "ipa-replica-prepare to create a new replica file.") + installer._fstore = fstore + installer._sstore = sstore + installer._config = config + @common_cleanup -def install(filename, options): - global config +def install(installer): + options = installer + fstore = installer._fstore + sstore = installer._sstore + config = installer._config dogtag_constants = dogtag.install_constants @@ -544,7 +525,7 @@ def install(filename, options): resolution_ok = ( check_dns_resolution(master, dns_masters) and check_dns_resolution(config.host_name, dns_masters)) - if not resolution_ok and not options.unattended: + if not resolution_ok and installer.interactive: if not ipautil.user_input("Continue?", False): sys.exit(0) else: @@ -562,7 +543,7 @@ def install(filename, options): replman.conn.unbind() # Configure ntpd - if options.conf_ntp: + if not options.no_ntp: ipaclient.ntpconf.force_ntpd(sstore) ntp = ntpinstance.NTPInstance() ntp.create_instance() @@ -584,8 +565,8 @@ def install(filename, options): ca.install(False, config, options) - krb = install_krb(config, setup_pkinit=options.setup_pkinit) - http = install_http(config, auto_redirect=options.ui_redirect) + krb = install_krb(config, setup_pkinit=not options.no_pkinit) + http = install_http(config, auto_redirect=not options.no_ui_redirect) otpd = otpdinstance.OtpdInstance() otpd.create_instance('OTPD', config.host_name, config.dirman_password, @@ -625,13 +606,13 @@ def install(filename, options): args = [paths.IPA_CLIENT_INSTALL, "--on-master", "--unattended", "--domain", config.domain_name, "--server", config.host_name, "--realm", config.realm_name] - if not options.create_sshfp: + if options.no_dns_sshfp: args.append("--no-dns-sshfp") - if options.trust_sshfp: + if options.ssh_trust_dns: args.append("--ssh-trust-dns") - if not options.conf_ssh: + if options.no_ssh: args.append("--no-ssh") - if not options.conf_sshd: + if options.no_sshd: args.append("--no-sshd") if options.mkhomedir: args.append("--mkhomedir") @@ -646,5 +627,228 @@ def install(filename, options): # Everything installed properly, activate ipa service. services.knownservices.ipa.enable() - destroy_private_ccache() - remove_replica_info_dir() + remove_replica_info_dir(installer) + + +class ReplicaCA(common.Installable, core.Group, core.Composite): + description = "certificate system" + + no_pkinit = Knob( + bool, False, + description="disables pkinit setup steps", + ) + + skip_schema_check = Knob( + bool, False, + description="skip check for updated CA DS schema on the remote master", + ) + + +class ReplicaDNS(common.Installable, core.Group, core.Composite): + description = "DNS" + + setup_dns = Knob( + bool, False, + description="configure bind with our zone", + ) + + forwarders = Knob( + (list, 'ip'), None, + description=("Add a DNS forwarder. This option can be used multiple " + "times"), + cli_name='forwarder', + ) + + no_forwarders = Knob( + bool, False, + description="Do not add any DNS forwarders, use root servers instead", + ) + + reverse_zones = Knob( + (list, str), [], + description=("The reverse DNS zone to use. This option can be used " + "multiple times"), + cli_name='reverse-zone', + ) + + no_reverse = Knob( + bool, False, + description="Do not create new reverse DNS zone", + ) + + no_dnssec_validation = Knob( + bool, False, + description="Disable DNSSEC validation", + ) + + no_host_dns = Knob( + bool, False, + description="Do not use DNS for hostname lookup during installation", + ) + + no_dns_sshfp = Knob( + bool, False, + description="do not automatically create DNS SSHFP records", + ) + + +class Replica(common.Installable, common.Interactive, core.Composite): + replica_file = Knob( + str, None, + description="a file generated by ipa-replica-prepare", + ) + + setup_ca = Knob( + bool, False, + initializable=False, + description="configure a dogtag CA", + ) + + setup_kra = Knob( + bool, False, + initializable=False, + description="configure a dogtag KRA", + ) + + ip_addresses = Knob( + (list, 'ip-local'), None, + description=("Replica server IP Address. This option can be used " + "multiple times"), + cli_name='ip-address', + ) + + password = Knob( + str, None, + sensitive=True, + description="Directory Manager (existing master) password", + cli_short_name='p', + ) + + master_password = Knob( + str, None, + sensitive=True, + deprecated=True, + description="kerberos master password (normally autogenerated)", + cli_short_name='P', + ) + + admin_password = Knob( + str, None, + sensitive=True, + description="Admin user Kerberos password used for connection check", + cli_short_name='w', + ) + + mkhomedir = Knob( + bool, False, + description="create home directories for users on their first login", + ) + + no_ntp = Knob( + bool, False, + description="do not configure ntp", + ) + + no_ui_redirect = Knob( + bool, False, + description="Do not automatically redirect to the Web UI", + ) + + ssh_trust_dns = Knob( + bool, False, + description="configure OpenSSH client to trust DNS SSHFP records", + ) + + no_ssh = Knob( + bool, False, + description="do not configure OpenSSH client", + ) + + no_sshd = Knob( + bool, False, + description="do not configure OpenSSH server", + ) + + skip_conncheck = Knob( + bool, False, + description="skip connection check to remote master", + ) + + def __init__(self, **kwargs): + super(Replica, self).__init__(**kwargs) + + self._top_dir = None + self._config = None + + #pylint: disable=no-member + + if self.replica_file is None: + raise RuntimeError( + "you must provide a file generated by ipa-replica-prepare") + if not ipautil.file_exists(self.replica_file): + raise RuntimeError( + "Replica file %s does not exist" % self.replica_file) + + if not self.dns.setup_dns: + if self.dns.forwarders: + raise RuntimeError( + "You cannot specify a --forwarder option without the " + "--setup-dns option") + if self.dns.no_forwarders: + raise RuntimeError( + "You cannot specify a --no-forwarders option without the " + "--setup-dns option") + if self.dns.reverse_zones: + raise RuntimeError( + "You cannot specify a --reverse-zone option without the " + "--setup-dns option") + if self.dns.no_reverse: + raise RuntimeError( + "You cannot specify a --no-reverse option without the " + "--setup-dns option") + if self.dns.no_dnssec_validation: + raise RuntimeError( + "You cannot specify a --no-dnssec-validation option " + "without the --setup-dns option") + elif self.dns.forwarders and self.dns.no_forwarders: + raise RuntimeError( + "You cannot specify a --forwarder option together with " + "--no-forwarders") + elif not self.dns.forwarders and not self.dns.no_forwarders: + raise RuntimeError( + "You must specify at least one --forwarder option or " + "--no-forwarders option") + elif self.dns.reverse_zones and self.dns.no_reverse: + raise RuntimeError( + "You cannot specify a --reverse-zone option together with " + "--no-reverse") + + # Automatically disable pkinit w/ dogtag until that is supported + self.ca.no_pkinit = True + + self.external_ca = False + self.external_cert_files = None + self.no_pkinit = self.ca.no_pkinit + self.skip_schema_check = self.ca.skip_schema_check + + self.setup_dns = self.dns.setup_dns + self.forwarders = self.dns.forwarders + self.no_forwarders = self.dns.no_forwarders + self.reverse_zones = self.dns.reverse_zones + self.no_reverse = self.dns.no_reverse + self.no_dnssec_validation = self.dns.no_dnssec_validation + self.dnssec_master = False + self.zonemgr = None + self.no_host_dns = self.dns.no_host_dns + self.no_dns_sshfp = self.dns.no_dns_sshfp + + self.unattended = not self.interactive + + @step() + def main(self): + install_check(self) + yield + install(self) + + ca = core.Component(ReplicaCA) + dns = core.Component(ReplicaDNS) |