Centralize timeout for waiting for servers to start.

All service start/restart currently go through ipapython/platform so
move the "wait for service to start" code there as well.

A dictionary of known services and ports to wait on is defined in base.py
This is referenced by the platforms by instance name to determine what
to wait for. For the case of dirsrv if we get that as a plain name
(no specific instance) it is assumed to be the main IPA service.

https://fedorahosted.org/freeipa/ticket/2375
https://fedorahosted.org/freeipa/ticket/2610
This commit is contained in:
Rob Crittenden
2012-05-24 11:23:36 -04:00
parent 6fb802152a
commit e5b6260008
16 changed files with 176 additions and 105 deletions

View File

@@ -681,7 +681,6 @@ class CAInstance(service.Service):
def __restart_instance(self):
try:
self.restart(PKI_INSTANCE_NAME)
installutils.wait_for_open_ports('localhost', 9180, 300)
except Exception:
# TODO: roll back here?
root_logger.critical("Failed to restart the certificate server. See the installation log for details.")

View File

@@ -416,7 +416,6 @@ class DsInstance(service.Service):
if not is_ds_running(instance):
root_logger.critical("Failed to restart the directory server. See the installation log for details.")
sys.exit(1)
installutils.wait_for_open_ports('localhost', self.open_ports, 300)
except SystemExit, e:
raise e
except Exception, e:
@@ -667,7 +666,7 @@ class DsInstance(service.Service):
# (re)start them.
for ds_instance in get_ds_instances():
try:
ipaservices.knownservices.dirsrv.restart(ds_instance)
ipaservices.knownservices.dirsrv.restart(ds_instance, wait=False)
except Exception, e:
root_logger.error('Unable to restart ds instance %s: %s', ds_instance, e)

View File

@@ -414,58 +414,6 @@ def create_keytab(path, principal):
kadmin("ktadd -k " + path + " " + principal)
def wait_for_open_ports(host, ports, timeout=0):
"""
Wait until the specified port(s) on the remote host are open. Timeout
in seconds may be specified to limit the wait.
"""
if not isinstance(ports, (tuple, list)):
ports = [ports]
op_timeout = time.time() + timeout
ipv6_failover = False
for port in ports:
while True:
try:
if ipv6_failover:
s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
else:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.close()
break;
except socket.error, e:
if e.errno == 111: # 111: Connection refused
if timeout and time.time() > op_timeout: # timeout exceeded
raise e
time.sleep(1)
elif not ipv6_failover: # fallback to IPv6 connection
ipv6_failover = True
else:
raise e
def wait_for_open_socket(socket_name, timeout=0):
"""
Wait until the specified socket on the local host is open. Timeout
in seconds may be specified to limit the wait.
"""
op_timeout = time.time() + timeout
while True:
try:
s = socket.socket(socket.AF_UNIX)
s.connect(socket_name)
s.close()
break;
except socket.error, e:
if e.errno in (2,111): # 111: Connection refused, 2: File not found
if timeout and time.time() > op_timeout: # timeout exceeded
raise e
time.sleep(1)
else:
raise e
def resolve_host(host_name):
try:
addrinfos = socket.getaddrinfo(host_name, None,

View File

@@ -34,6 +34,14 @@ class DSRestart(service.Service):
"""
service.Service.__init__(self, "dirsrv")
def start(self, instance_name="", capture_output=True, wait=True):
"""
During upgrades the server is listening only on the socket so
we don't want to wait on ports. The caller is responsible for
waiting for the socket to be ready.
"""
super(DSRestart, self).start(wait=False)
def create_instance(self):
self.step("stopping directory server", self.stop)
self.step("starting directory server", self.start)

View File

@@ -18,11 +18,11 @@
#
import os
from ipaserver.install import installutils
from ipaserver.install.plugins import FIRST, MIDDLE, LAST
from ipaserver.install.plugins import POST_UPDATE
from ipaserver.install.plugins.baseupdate import DSRestart
from ipaserver.install.ldapupdate import LDAPUpdate
from ipapython.ipautil import wait_for_open_socket
from ipalib import api
from ipalib import backend
import ldap as _ldap
@@ -161,7 +161,7 @@ class updateclient(backend.Executioner):
if live_run:
self.destroy_context()
dsrestart.create_instance()
installutils.wait_for_open_socket(socket_name)
wait_for_open_socket(socket_name)
self.create_context(dm_password)
else:
self.log.warn("Test mode, skipping restart")

View File

@@ -25,7 +25,6 @@ import sys
import ldap
from ipaserver import ipaldap
from ipapython import services as ipaservices
import installutils
from ldap import modlist
from ipalib import api, util, errors
from ipapython import ipautil
@@ -92,7 +91,6 @@ def enable_replication_version_checking(hostname, realm, dirman_passwd):
conn.unbind()
serverid = "-".join(realm.split("."))
ipaservices.knownservices.dirsrv.restart(instance_name=serverid)
installutils.wait_for_open_ports('localhost', [389, 636], 300)
else:
conn.unbind()

View File

@@ -35,6 +35,8 @@ from ipapython.ipa_log_manager import *
CACERT = "/etc/ipa/ca.crt"
# The service name as stored in cn=masters,cn=ipa,cn=etc. In the tuple
# the first value is the *nix service name, the second the start order.
SERVICE_LIST = {
'KDC':('krb5kdc', 10),
'KPASSWD':('kadmin', 20),
@@ -198,11 +200,11 @@ class Service(object):
def stop(self, instance_name="", capture_output=True):
self.service.stop(instance_name, capture_output=capture_output)
def start(self, instance_name="", capture_output=True):
self.service.start(instance_name, capture_output=capture_output)
def start(self, instance_name="", capture_output=True, wait=True):
self.service.start(instance_name, capture_output=capture_output, wait=wait)
def restart(self, instance_name="", capture_output=True):
self.service.restart(instance_name, capture_output=capture_output)
def restart(self, instance_name="", capture_output=True, wait=True):
self.service.restart(instance_name, capture_output=capture_output, wait=wait)
def is_running(self):
return self.service.is_running()

View File

@@ -60,6 +60,11 @@ class IPAUpgrade(service.Service):
self.badsyntax = False
self.upgradefailed = False
def start(self, instance_name="", capture_output=True, wait=True):
# Don't wait here because we've turned off port 389. The connection
# we make will wait for the socket.
super(IPAUpgrade, self).start(instance_name, capture_output, wait=False)
def create_instance(self):
self.step("stopping directory server", self.stop)
self.step("saving configuration", self.__save_config)