On Sat, 2011-05-28 at 00:10 -0400, Rob Crittenden wrote:
> Martin Kosek wrote:
> > On Mon, 2011-05-23 at 16:41 -0400, Rob Crittenden wrote:
> >> Martin Kosek wrote:
> >>> This is a first version of connection checking program for replica
> >>> installation. See patch for program purpose description. Currently,
> >>> there is no man pages for the program.
> >>>
> >>> Note to Simo and Rob: I use password for logging as admin. Btw would it
> >>> be safe to have an admin keytab in the replica file? Replica file
> >>> contents are lying freely in /tmp after the replica installation.
> >>>
> >>> Martin
> >>
> >> nack, you aren't including the new binary in the spec.
> >
> > Oh, thanks for this one.
> >
> >>
> >> You should also:
> >>
> >> - set KRB5CCNAME to a temporary ccache and remove that when the install
> >> exists (successful or not)
> >
> > Done.
> >
> >> - remove the temporary krb5.conf you create
> >
> > Done.
> >
> >> - be a bit more explicit what we are doing, at least more than "Run
> >> connection check to master".
> >
> > Actually, I am if you run the new script separately. I removed "--quiet"
> > parameter passed to the script in ipa-replica-install so that it is more
> > verbose. Plus, I improved texts sent to the user.
> >
> >> - yes, we should remove the replica file contents
> >
> > I enhanced ipa-replica-install to do that.
> >
> > Martin
> >
> 
> Works great until the very end:
> ...
> ...
> 
> Execute check on remote master
> Check connection from master to remote replica 'slinky.greyoak.com':
>     Directory Service: unsecure port (389): FAILED
>     Directory Service: secure port (636): FAILED
>     Kerberos (88): OK
> 
> Remote master check failed with following error message(s):
> Could not chdir to home directory /home/admin: No such file or directory
> Port check failed! Unaccessible port(s): 389, 636
> 
> Connection check failed with following error: None
> 
> rob

Right, I introduced this wrong error message in the last patch. I fixed
this one and also one typo. Updated patch attached.

Martin
>From ac6c38804498480c472106b054121d4aafc8423a Mon Sep 17 00:00:00 2001
From: Martin Kosek <mko...@redhat.com>
Date: Sun, 22 May 2011 19:17:07 +0200
Subject: [PATCH] Connection check program for replica installation

When connection between a master machine and future replica is not
sane, the replica installation may fail unexpectedly with
inconvenient error messages. One common problem is misconfigured
firewall.

This patch adds a program ipa-replica-conncheck which tests the
connection using the following procedure:

1) Execute the on-replica check testing the connection to master
2) Open required ports on local machine
3) Ask user to run the on-master part of the check OR run it
   automatically:
     a) kinit to master as default admin user with given password
     b) run the on-master part using ssh
4) When master part is executed, it checks connection back to
   the replica and prints the check result

This program is run by ipa-replica-install as mandatory part. It
can, however, be skipped using --skip-conncheck option.
ipa-replica-install now requires password for admin user to run
the command on remote master.

https://fedorahosted.org/freeipa/ticket/1107
---
 freeipa.spec.in                         |    1 +
 install/tools/ipa-replica-conncheck     |  372 +++++++++++++++++++++++++++++++
 install/tools/ipa-replica-install       |   40 ++++
 install/tools/man/ipa-replica-install.1 |    6 +
 ipapython/ipautil.py                    |   73 ++++++
 5 files changed, 492 insertions(+), 0 deletions(-)
 create mode 100755 install/tools/ipa-replica-conncheck

diff --git a/freeipa.spec.in b/freeipa.spec.in
index b9366165a6efe9515e9b3527947d301948a714f5..5042bfe592014b49b0691081831e603e6156e8ce 100644
--- a/freeipa.spec.in
+++ b/freeipa.spec.in
@@ -357,6 +357,7 @@ fi
 %doc COPYING README Contributors.txt
 %{_sbindir}/ipa-dns-install
 %{_sbindir}/ipa-server-install
+%{_sbindir}/ipa-replica-conncheck
 %{_sbindir}/ipa-replica-install
 %{_sbindir}/ipa-replica-prepare
 %{_sbindir}/ipa-replica-manage
diff --git a/install/tools/ipa-replica-conncheck b/install/tools/ipa-replica-conncheck
new file mode 100755
index 0000000000000000000000000000000000000000..5030e5da7866de3558d2ffa7fa4a89dcc2ccf70f
--- /dev/null
+++ b/install/tools/ipa-replica-conncheck
@@ -0,0 +1,372 @@
+#! /usr/bin/python -E
+# Authors: Martin Kosek <mko...@redhat.com>
+#
+# Copyright (C) 2011  Red Hat
+# see file 'COPYING' for use and warranty information
+#
+# 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/>.
+#
+
+from ipapython.config import IPAOptionParser
+from ipapython import version
+from ipapython import ipautil
+from ipapython.ipautil import CalledProcessError
+import ipaclient.ipachangeconf
+from optparse import OptionGroup
+import logging
+import sys
+import os
+import signal
+import tempfile
+import getpass
+import socket
+import time
+import threading
+import errno
+
+CONNECT_TIMEOUT = 5
+RESPONDERS = [ ]
+QUIET = False
+CCACHE_FILE = "/etc/ipa/.conncheck_ccache"
+KRB5_CONFIG = None
+
+class CheckedPort(object):
+    def __init__(self, port, stream, description):
+        self.port = port
+        self.stream = stream
+        self.description = description
+
+BASE_PORTS = [ 
+                CheckedPort(389, True, "Directory Service: unsecure port"),
+                CheckedPort(636, True, "Directory Service: secure port"),
+                CheckedPort(88, False, "Kerberos"),
+             ]
+
+CA_PORTS  = [
+                CheckedPort(7389, True, "PKI-CA: Directory Service"),
+                CheckedPort(9444, True, "PKI-CA: EE Secure port"),
+                CheckedPort(9445, True, "PKI-CA: Admin Secure port"),
+                CheckedPort(9446, True, "PKI-CA: EE Secure Client Auth port"),
+                CheckedPort(9180, True, "PKI-CA: Unsecure port"),
+            ]
+
+def print_info(msg):
+    if not QUIET:
+        print msg
+
+def parse_options():
+    parser = IPAOptionParser(version=version.VERSION)
+
+    replica_group = OptionGroup(parser, "on-replica options")
+    replica_group.add_option("-m", "--master", dest="master",
+                      help="Master address with running IPA for output connection check")
+    replica_group.add_option("-a", "--auto-master-check", dest="auto_master_check",
+                      action="store_true",
+                      default=False,
+                      help="Automatically execute connection check on master")
+    replica_group.add_option("-r", "--realm", dest="realm",
+                      help="Realm name")
+    replica_group.add_option("-k", "--kdc", dest="kdc",
+                      help="Master KDC. Defaults to master address")
+    replica_group.add_option("-p", "--principal", dest="principal",
+                      default="admin", help="Principal to use to log in to remote master")
+    replica_group.add_option("-w", "--password", dest="password", sensitive=True,
+                      help="Password for the principal"),
+    parser.add_option_group(replica_group)
+
+
+    master_group = OptionGroup(parser, "on-master options")
+    master_group.add_option("-R", "--replica", dest="replica",
+                      help="Address of remote replica machine to check against")
+    parser.add_option_group(master_group)
+
+    common_group = OptionGroup(parser, "common options")
+    common_group.add_option("-c", "--check-ca", dest="check_ca",
+                      action="store_true",
+                      default=False,
+                      help="Check also ports for Certificate Authority")
+
+    common_group.add_option("", "--hostname", dest="hostname",
+                      help="The hostname of this server (FQDN). "
+                           "By default of nodename from uname(2) is used.")
+    parser.add_option_group(common_group)
+
+    parser.add_option("-d", "--debug", dest="debug",
+                      action="store_true",
+                      default=False, help="Print debugging information")
+    parser.add_option("-q", "--quiet", dest="quiet",
+                      action="store_true",
+                      default=False, help="Output only errors")
+
+    options, args = parser.parse_args()
+    safe_options = parser.get_safe_opts(options)
+
+    if options.master and options.replica:
+        parser.error("on-master and on-replica options are mutually exclusive!")
+
+    if options.master:
+        if options.auto_master_check and not options.realm:
+            parser.error("Realm is parameter is required to connect to remote master!")
+        if not os.getegid() == 0:
+            parser.error("You can only run on-replica part as root.")
+
+    if options.master and not options.kdc:
+       options.kdc = options.master
+
+    if not options.master and not options.replica:
+       parser.error("No action: you should select either --replica or --master option.")
+
+    if not options.hostname:
+        options.hostname = socket.getfqdn()
+
+    if options.quiet:
+        global QUIET
+        QUIET = True
+
+    return safe_options, options
+
+def logging_setup(options):
+    if os.getegid() == 0:
+        log_file = "/var/log/ipareplica-conncheck.log"
+        old_umask = os.umask(077)
+        logging.basicConfig(level=logging.DEBUG,
+                        format='%(asctime)s %(levelname)s %(message)s',
+                        filename=log_file,
+                        filemode='w')
+        os.umask(old_umask)
+
+    console = logging.StreamHandler()
+    # If the debug option is set, also log debug messages to the console
+    if options.debug:
+        console.setLevel(logging.DEBUG)
+    else:
+        # Otherwise, log critical and error messages
+        console.setLevel(logging.ERROR)
+    formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
+    console.setFormatter(formatter)
+    logging.getLogger('').addHandler(console)
+
+def clean_responders(responders):
+    if not responders:
+        return
+
+    for responder in responders:
+        responder.stop()
+
+    for responder in responders:
+        responder.join()
+        responders.remove(responder)
+
+def sigterm_handler(signum, frame):
+    print_info("\nCleaning up...")
+
+    global RESPONDERS
+    clean_responders(RESPONDERS)
+
+    sys.exit(1)
+
+def configure_krb5_conf(realm, kdc, filename):
+
+    krbconf = ipaclient.ipachangeconf.IPAChangeConf("IPA Installer")
+    krbconf.setOptionAssignment(" = ")
+    krbconf.setSectionNameDelimiters(("[","]"))
+    krbconf.setSubSectionDelimiters(("{","}"))
+    krbconf.setIndent(("","  ","    "))
+
+    opts = [{'name':'comment', 'type':'comment', 'value':'File created by ipa-replica-conncheck'},
+            {'name':'empty', 'type':'empty'}]
+
+    #[libdefaults]
+    libdefaults = [{'name':'default_realm', 'type':'option', 'value':realm}]
+    libdefaults.append({'name':'dns_lookup_realm', 'type':'option', 'value':'false'})
+    libdefaults.append({'name':'dns_lookup_kdc', 'type':'option', 'value':'false'})
+    libdefaults.append({'name':'rdns', 'type':'option', 'value':'false'})
+    libdefaults.append({'name':'ticket_lifetime', 'type':'option', 'value':'24h'})
+    libdefaults.append({'name':'forwardable', 'type':'option', 'value':'yes'})
+
+    opts.append({'name':'libdefaults', 'type':'section', 'value': libdefaults})
+    opts.append({'name':'empty', 'type':'empty'})
+
+    #the following are necessary only if DNS discovery does not work
+    #[realms]
+    realms_info =[{'name':'kdc', 'type':'option', 'value':kdc+':88'},
+                 {'name':'admin_server', 'type':'option', 'value':kdc+':749'}]
+    realms = [{'name':realm, 'type':'subsection', 'value':realms_info}]
+
+    opts.append({'name':'realms', 'type':'section', 'value':realms})
+    opts.append({'name':'empty', 'type':'empty'})
+
+    #[appdefaults]
+    pamopts = [{'name':'debug', 'type':'option', 'value':'false'},
+               {'name':'ticket_lifetime', 'type':'option', 'value':'36000'},
+               {'name':'renew_lifetime', 'type':'option', 'value':'36000'},
+               {'name':'forwardable', 'type':'option', 'value':'true'},
+               {'name':'krb4_convert', 'type':'option', 'value':'false'}]
+    appopts = [{'name':'pam', 'type':'subsection', 'value':pamopts}]
+    opts.append({'name':'appdefaults', 'type':'section', 'value':appopts})
+
+    logging.debug("Writing temporary Kerberos configuration to %s:\n%s"
+            % (filename, krbconf.dump(opts)))
+
+    krbconf.newConf(filename, opts)
+
+class PortResponder(threading.Thread):
+
+    def __init__(self, port, socket_stream = True, socket_timeout=1):
+        super(PortResponder, self).__init__()
+        self.port = port
+        self.socket_stream = socket_stream
+        self.socket_timeout = socket_timeout
+        self._stop_request = False
+
+    def run(self):
+        while not self._stop_request:
+            try:
+                ipautil.bind_port_responder(self.port, self.socket_stream,
+                        self.socket_timeout, responder_data="FreeIPA")
+            except socket.timeout:
+                pass
+            except socket.error, e:
+                if e.errno == errno.EADDRINUSE:
+                    time.sleep(1)
+                else:
+                    raise
+
+    def stop(self):
+        self._stop_request = True
+
+def port_check(host, port_list):
+    failed_ports = []
+    for port in port_list:
+        if ipautil.host_port_open(host, port.port, port.stream, CONNECT_TIMEOUT):
+            result = "OK"
+        else:
+            failed_ports.append(port)
+            result = "FAILED"
+        print_info("   %s (%d): %s" % (port.description, port.port, result))
+    
+    if failed_ports:
+        msg_ports = ", ".join([str(port.port) for port in failed_ports])
+        raise RuntimeError("Port check failed! Inaccessible port(s): %s" % msg_ports)
+
+def main():
+    safe_options, options = parse_options()
+
+    logging_setup(options)
+    logging.debug('%s was invoked with options: %s' % (sys.argv[0], safe_options))
+    logging.debug("missing options might be asked for interactively later\n")
+
+    signal.signal(signal.SIGTERM, sigterm_handler)
+    signal.signal(signal.SIGINT, sigterm_handler)
+
+    required_ports = BASE_PORTS
+    if options.check_ca:
+        required_ports.extend(CA_PORTS)
+
+    if options.replica:
+        print_info("Check connection from master to remote replica '%s':" % options.replica)
+        port_check(options.replica, required_ports)
+        print_info("\nConnection from master to replica is OK.")
+
+    # kinit to foreign master
+    if options.master:
+        # check ports on master first
+        print_info("Check connection from replica to remote master '%s':" % options.master)
+        port_check( options.master, required_ports)
+        print_info("\nConnection from replica to master is OK.")
+
+        # create listeners
+        global RESPONDERS
+        print_info("Start listening on required ports for remote master check")
+        for port in required_ports:
+            logging.debug("Start listening on port %d (%s)" % (port.port, port.description))
+            responder = PortResponder(port.port, port.stream)
+            responder.start()
+            RESPONDERS.append(responder)
+
+        if options.auto_master_check:
+            (krb_fd, krb_name) = tempfile.mkstemp()
+            os.close(krb_fd)
+            configure_krb5_conf(options.realm, options.kdc, krb_name)
+            global KRB5_CONFIG
+            KRB5_CONFIG = krb_name
+
+            print_info("Get credentials to log in to remote master")
+            if options.principal.find('@') == -1:
+                principal = '%s@%s' % (options.principal, options.realm)
+                user = options.principal
+            else:
+                principal = options.principal
+                user = options.principal.partition('@')[0]
+            
+            if options.password:
+                password=options.password
+            else:
+                password = getpass.getpass("Password for %s: " % principal)
+            
+            stderr=''
+            (stdout, stderr, returncode) = ipautil.run(['/usr/bin/kinit', principal],
+                 env={'KRB5_CONFIG':KRB5_CONFIG, 'KRB5CCNAME':CCACHE_FILE},
+                 stdin=password, raiseonerr=False)
+            if returncode != 0:
+                raise RuntimeError("Cannot acquire Kerberos ticket: %s" % stderr)
+
+            remote_check_opts = ['--replica %s' % options.hostname]
+            if options.check_ca:
+                remote_check_opts.append('--check-ca')
+
+            print_info("Execute check on remote master")
+            
+            stderr = ''
+            remote_addr = "%s@%s" % (user, options.master)
+            (stdout, stderr, returncode) = ipautil.run(['/usr/bin/ssh', remote_addr,
+                "/usr/sbin/ipa-replica-conncheck " + " ".join(remote_check_opts)],
+                env={'KRB5_CONFIG':KRB5_CONFIG, 'KRB5CCNAME' : CCACHE_FILE},
+                raiseonerr=False)
+
+            print_info(stdout)
+
+            if returncode != 0:
+                raise RuntimeError("Remote master check failed with following error message(s):\n%s" % stderr)
+        else:
+            # wait until user  test is ready
+            print_info("Listeners are started. Use CTRL+C to terminate the listening part after the test.")
+            print_info("")
+            print_info("Please run the following command on remote master:")
+
+            remote_check_opts = ['--replica %s' % options.hostname]
+            if options.check_ca:
+                remote_check_opts.append('--check-ca')
+            print_info("/usr/sbin/ipa-replica-conncheck " + " ".join(remote_check_opts))
+            time.sleep(3600)
+            print_info("Connection check timeout: terminating listening program")
+
+if __name__ == "__main__":
+    try:
+        sys.exit(main())
+    except SystemExit, e:
+        sys.exit(e)
+    except KeyboardInterrupt:
+        sys.exit(1)
+    except RuntimeError, e:
+        sys.exit(e)
+    finally:
+        clean_responders(RESPONDERS)
+        for file_name in (CCACHE_FILE, KRB5_CONFIG):
+            if file_name:
+                try:
+                    os.remove(file_name)
+                except OSError:
+                    pass
+
diff --git a/install/tools/ipa-replica-install b/install/tools/ipa-replica-install
index 293a0a06c8e4ff608d8327135ea1b4e008ab4d33..1b84daef107734c782a67710a356356e4f9f1971 100755
--- a/install/tools/ipa-replica-install
+++ b/install/tools/ipa-replica-install
@@ -38,6 +38,7 @@ from ipapython.config import IPAOptionParser
 from ipapython import sysrestore
 
 CACERT="/etc/ipa/ca.crt"
+REPLICA_INFO_TOP_DIR=None
 
 class ReplicaConfig:
     def __init__(self):
@@ -58,6 +59,8 @@ def parse_options():
                       default=False, help="gather extra debugging information")
     parser.add_option("-p", "--password", dest="password", sensitive=True,
                       help="Directory Manager (existing master) password")
+    parser.add_option("-w", "--admin-password", dest="admin_password", sensitive=True,
+                      help="Admin user Kerberos password used for connection check")
     parser.add_option("--setup-dns", dest="setup_dns", action="store_true",
                       default=False, help="configure bind with our zone")
     parser.add_option("--forwarder", dest="forwarders", action="append",
@@ -71,6 +74,8 @@ def parse_options():
                       help="Do not use DNS for hostname lookup during installation")
     parser.add_option("--no-pkinit", dest="setup_pkinit", action="store_false",
                       default=True, help="disables pkinit setup steps")
+    parser.add_option("--skip-conncheck", dest="skip_conncheck", action="store_true",
+                      default=False, help="skip connection check to remote master")
     parser.add_option("-U", "--unattended", dest="unattended", action="store_true",
                       default=False, help="unattended installation never prompts the user")
 
@@ -382,6 +387,8 @@ def main():
 
     try:
         top_dir, dir = expand_info(filename, dirman_password)
+        global REPLICA_INFO_TOP_DIR
+        REPLICA_INFO_TOP_DIR = top_dir
     except Exception, e:
         print "ERROR: Failed to decrypt or open the replica file."
         print "Verify you entered the correct Directory Manager password."
@@ -402,6 +409,32 @@ def main():
             sys.exit(0)
     config.dir = dir
 
+
+    # check connection
+    if not options.skip_conncheck:
+        print "Run connection check to master"
+        args = ["/usr/sbin/ipa-replica-conncheck", "--master", config.master_host_name,
+                "--auto-master-check", "--realm", config.realm_name,
+                "--principal", "admin",
+                "--hostname", config.host_name]
+
+        if options.admin_password:
+            args.extend(["--password", options.admin_password])
+
+        cafile = config.dir + "/cacert.p12"
+        if ipautil.file_exists(cafile): # with CA
+            args.append('--check-ca')
+        logging.debug("Running ipa-replica-conncheck with following arguments: %s" %
+                " ".join(args))
+        (stdin, stderr, returncode) = ipautil.run(args,raiseonerr=False, capture_output=False)
+
+        if returncode != 0:
+            sys.exit("Connection check failed!" + 
+                     "\nPlease fix your network settings according to error messages above." +
+                     "\nIf the check results are not valid it can be skipped with --skip-conncheck parameter.")
+        else:
+            print "Connection check OK"
+
     # Create the management framework config file
     # Note: We must do this before bootstraping and finalizing ipalib.api
     fd = open("/etc/ipa/default.conf", "w")
@@ -549,6 +582,13 @@ except Exception, e:
     logging.debug(message)
 except KeyboardInterrupt:
     print "Installation cancelled." 
+finally:
+    # always try to remove decrypted replica file
+    try:
+        if REPLICA_INFO_TOP_DIR:
+            shutil.rmtree(REPLICA_INFO_TOP_DIR)
+    except OSError:
+        pass
 
 print ""
 print "Your system may be partly configured." 
diff --git a/install/tools/man/ipa-replica-install.1 b/install/tools/man/ipa-replica-install.1
index 3ee304224bb6db249b74cca736e95bba2c4356af..8889235462ef52327c951714ab62982b5003c8cc 100644
--- a/install/tools/man/ipa-replica-install.1
+++ b/install/tools/man/ipa-replica-install.1
@@ -36,6 +36,9 @@ Enable debug logging when more verbose output is needed
 \fB\-p\fR, \fB\-\-password\fR=\fIDM_PASSWORD\fR
 Directory Manager (existing master) password
 .TP
+\fB\-w\fR \fIADMIN_PASSWORD\fR, \fB\-\-admin\-password\fR=\fIADMIN_PASSWORD\fR
+Admin user Kerberos password used for connection check
+.TP
 \fB\-\-setup\-dns\fR
 Generate a DNS zone if it does not exist already and configure the DNS server.
 This option requires that you either specify at least one DNS forwarder through
@@ -58,6 +61,9 @@ Do not use DNS for hostname lookup during installation
 \fB\-\-no\-pkinit\fR
 Disables pkinit setup steps
 .TP
+\fB\-\-skip\-conncheck\fR
+Skip connection check to remote master
+.TP
 \fB\-U\fR, \fB\-\-unattended\fR
 An unattended installation that will never prompt for user input
 .SH "EXIT STATUS"
diff --git a/ipapython/ipautil.py b/ipapython/ipautil.py
index 4280cd9f4f8ff6a98f5ff9808d8a9c6cfe8df75b..d521c27fd6f2ccd69882641c4b1222f272b9c8ed 100644
--- a/ipapython/ipautil.py
+++ b/ipapython/ipautil.py
@@ -32,6 +32,7 @@ import copy
 import stat
 import shutil
 import urllib2
+import socket
 
 from ipapython import ipavalidate
 from types import *
@@ -1015,3 +1016,75 @@ def chkconfig_add(service_name):
 def chkconfig_del(service_name):
     run(["/sbin/chkconfig", "--del", service_name])
 
+def host_port_open(host, port, socket_stream=True, socket_timeout=None):
+    families = (socket.AF_INET, socket.AF_INET6)
+    success = False
+
+    if socket_stream:
+        socket_type = socket.SOCK_STREAM
+    else:
+        socket_type = socket.SOCK_DGRAM
+
+    for family in families:
+        try:
+            try:
+                s = socket.socket(family, socket_type)
+            except socket.error:
+                continue
+
+            if socket_timeout is not None:
+                s.settimeout(socket_timeout)
+            
+            s.connect((host, port))
+            success = True
+        except socket.error, e:
+            pass
+        finally:
+            s.close()
+        
+        if success:
+            return True
+
+    return False
+
+def bind_port_responder(port, socket_stream=True, socket_timeout=None, responder_data=None):
+    families = (socket.AF_INET, socket.AF_INET6)
+
+    if socket_stream:
+        socket_type = socket.SOCK_STREAM
+    else:
+        socket_type = socket.SOCK_DGRAM
+
+    host = ''   # all available interfaces
+
+    for family in families:
+        try:
+            s = socket.socket(family, socket_type)
+        except socket.error, e:
+            if family == families[-1]:  # last available family
+                raise e
+
+    if socket_timeout is not None:
+        s.settimeout(socket_timeout)
+
+    if socket_stream:
+        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
+
+    try:
+        s.bind((host, port))
+
+        if socket_stream:
+            s.listen(1)
+            connection, client_address = s.accept()
+            try:
+                if responder_data:
+                    connection.sendall(responder_data) #pylint: disable=E1101
+            finally:
+                connection.close()
+        else:
+            data, addr = s.recvfrom( 512 ) # buffer size is 1024 bytes
+
+            if responder_data:
+                s.sendto(responder_data, addr)
+    finally:
+        s.close()
-- 
1.7.5.1

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to