463 lines
20 KiB
Diff
463 lines
20 KiB
Diff
From 68d5fe1ec7d785f127b3513f84cc632cdb1f9167 Mon Sep 17 00:00:00 2001
|
|
From: Alexander Bokovoy <abokovoy@redhat.com>
|
|
Date: Fri, 13 Jul 2012 18:12:48 +0300
|
|
Subject: [PATCH 55/79] Ensure ipa-adtrust-install is run with Kerberos ticket
|
|
for admin user
|
|
|
|
When setting up AD trusts support, ipa-adtrust-install utility
|
|
needs to be run as:
|
|
- root, for performing Samba configuration and using LDAPI/autobind
|
|
- kinit-ed IPA admin user, to ensure proper ACIs are granted to
|
|
fetch keytab
|
|
|
|
As result, we can get rid of Directory Manager credentials in ipa-adtrust-install
|
|
|
|
https://fedorahosted.org/freeipa/ticket/2815
|
|
---
|
|
install/tools/ipa-adtrust-install | 46 +++++++------
|
|
install/tools/man/ipa-adtrust-install.1 | 3 -
|
|
ipaserver/install/adtrustinstance.py | 21 +++---
|
|
ipaserver/install/bindinstance.py | 2 +-
|
|
ipaserver/install/cainstance.py | 3 +-
|
|
ipaserver/install/dsinstance.py | 2 +-
|
|
ipaserver/install/krbinstance.py | 2 +-
|
|
ipaserver/install/service.py | 114 +++++++++++++++++++++-----------
|
|
8 files changed, 116 insertions(+), 77 deletions(-)
|
|
|
|
diff --git a/install/tools/ipa-adtrust-install b/install/tools/ipa-adtrust-install
|
|
index 6678018e6346d75d5042894cfb833d38079d3f21..02a309306fb5743c94b651ab22afa06b5eb2cc8b 100755
|
|
--- a/install/tools/ipa-adtrust-install
|
|
+++ b/install/tools/ipa-adtrust-install
|
|
@@ -24,7 +24,7 @@
|
|
from ipaserver.plugins.ldap2 import ldap2
|
|
from ipaserver.install import adtrustinstance
|
|
from ipaserver.install.installutils import *
|
|
-from ipaserver.install import installutils
|
|
+from ipaserver.install import service
|
|
from ipapython import version
|
|
from ipapython import ipautil, sysrestore
|
|
from ipalib import api, errors, util
|
|
@@ -37,8 +37,6 @@ log_file_name = "/var/log/ipaserver-install.log"
|
|
|
|
def parse_options():
|
|
parser = IPAOptionParser(version=version.VERSION)
|
|
- parser.add_option("-p", "--ds-password", dest="dm_password",
|
|
- sensitive=True, help="directory manager password")
|
|
parser.add_option("-d", "--debug", dest="debug", action="store_true",
|
|
default=False, help="print debugging information")
|
|
parser.add_option("--ip-address", dest="ip_address",
|
|
@@ -98,7 +96,7 @@ def main():
|
|
root_logger.debug('%s was invoked with options: %s' % (sys.argv[0], safe_options))
|
|
root_logger.debug("missing options might be asked for interactively later\n")
|
|
|
|
- installutils.check_server_configuration()
|
|
+ check_server_configuration()
|
|
|
|
global fstore
|
|
fstore = sysrestore.FileStore('/var/lib/ipa/sysrestore')
|
|
@@ -194,24 +192,34 @@ def main():
|
|
if not options.unattended and ( not netbios_name or not options.netbios_name):
|
|
netbios_name = read_netbios_name(netbios_name)
|
|
|
|
- dm_password = options.dm_password or read_password("Directory Manager",
|
|
- confirm=False, validate=False)
|
|
- smb = adtrustinstance.ADTRUSTInstance(fstore, dm_password)
|
|
+ try:
|
|
+ ctx = krbV.default_context()
|
|
+ ccache = ctx.default_ccache()
|
|
+ principal = ccache.principal()
|
|
+ except krbV.Krb5Error, e:
|
|
+ sys.exit("Must have Kerberos credentials to setup AD trusts on server")
|
|
|
|
- # try the connection
|
|
try:
|
|
- smb.ldap_connect()
|
|
- smb.ldap_disconnect()
|
|
- except ldap.INVALID_CREDENTIALS, e:
|
|
- sys.exit("Password is not valid!")
|
|
+ api.Backend.ldap2.connect(ccache.name)
|
|
+ except errors.ACIError, e:
|
|
+ sys.exit("Outdated Kerberos credentials. Use kdestroy and kinit to update your ticket")
|
|
+ except errors.DatabaseError, e:
|
|
+ sys.exit("Cannot connect to the LDAP database. Please check if IPA is running")
|
|
|
|
- if smb.dm_password:
|
|
- api.Backend.ldap2.connect(bind_dn="cn=Directory Manager", bind_pw=smb.dm_password)
|
|
- else:
|
|
- # See if our LDAP server is up and we can talk to it over GSSAPI
|
|
- ccache = krbV.default_context().default_ccache().name
|
|
- api.Backend.ldap2.connect(ccache)
|
|
+ try:
|
|
+ user = api.Command.user_show(unicode(principal[0]))['result']
|
|
+ group = api.Command.group_show(u'admins')['result']
|
|
+ if not (user['uid'][0] in group['member_user'] and
|
|
+ group['cn'][0] in user['memberof_group']):
|
|
+ raise errors.RequirementError(name='admins group membership')
|
|
+ except errors.RequirementError, e:
|
|
+ sys.exit("Must have administrative privileges to setup AD trusts on server")
|
|
+ except Exception, e:
|
|
+ sys.exit("Unrecognized error during check of admin rights: %s" % (str(e)))
|
|
|
|
+ smb = adtrustinstance.ADTRUSTInstance(fstore)
|
|
+ smb.realm = api.env.realm
|
|
+ smb.autobind = service.ENABLED
|
|
smb.setup(api.env.host, ip_address, api.env.realm, api.env.domain,
|
|
netbios_name, options.rid_base, options.secondary_rid_base,
|
|
options.no_msdcs)
|
|
@@ -250,5 +258,5 @@ information"""
|
|
return 0
|
|
|
|
if __name__ == '__main__':
|
|
- installutils.run_script(main, log_file_name=log_file_name,
|
|
+ run_script(main, log_file_name=log_file_name,
|
|
operation_name='ipa-adtrust-install')
|
|
diff --git a/install/tools/man/ipa-adtrust-install.1 b/install/tools/man/ipa-adtrust-install.1
|
|
index b61da19088b40d6a9e53784f9a061913ecda4321..22337c3df8827670657bf405b6c49ba2f8624d6d 100644
|
|
--- a/install/tools/man/ipa-adtrust-install.1
|
|
+++ b/install/tools/man/ipa-adtrust-install.1
|
|
@@ -27,9 +27,6 @@ trust to an Active Directory domain. This requires that the IPA server is
|
|
already installed and configured.
|
|
.SH "OPTIONS"
|
|
.TP
|
|
-\fB\-p\fR \fIDM_PASSWORD\fR, \fB\-\-ds\-password\fR=\fIDM_PASSWORD\fR
|
|
-The password to be used by the Directory Server for the Directory Manager user
|
|
-.TP
|
|
\fB\-d\fR, \fB\-\-debug\fR
|
|
Enable debug logging when more verbose output is needed
|
|
.TP
|
|
diff --git a/ipaserver/install/adtrustinstance.py b/ipaserver/install/adtrustinstance.py
|
|
index 20feec4df309b5793aa1c29fdf18bc5bfe180943..9dcbec2d61d935f90e74cc65b30a0f1d0c0f9d2a 100644
|
|
--- a/ipaserver/install/adtrustinstance.py
|
|
+++ b/ipaserver/install/adtrustinstance.py
|
|
@@ -96,10 +96,9 @@ class ADTRUSTInstance(service.Service):
|
|
OBJC_GROUP = "ipaNTGroupAttrs"
|
|
OBJC_DOMAIN = "ipaNTDomainAttrs"
|
|
|
|
- def __init__(self, fstore=None, dm_password=None):
|
|
+ def __init__(self, fstore=None):
|
|
self.fqdn = None
|
|
self.ip_address = None
|
|
- self.realm_name = None
|
|
self.domain_name = None
|
|
self.netbios_name = None
|
|
self.no_msdcs = None
|
|
@@ -118,7 +117,7 @@ class ADTRUSTInstance(service.Service):
|
|
self.rid_base = None
|
|
self.secondary_rid_base = None
|
|
|
|
- service.Service.__init__(self, "smb", dm_password=dm_password)
|
|
+ service.Service.__init__(self, "smb", dm_password=None, ldapi=True)
|
|
|
|
if fstore:
|
|
self.fstore = fstore
|
|
@@ -436,6 +435,8 @@ class ADTRUSTInstance(service.Service):
|
|
# We do not let the system start IPA components on its own,
|
|
# Instead we reply on the IPA init script to start only enabled
|
|
# components as found in our LDAP configuration tree
|
|
+ # Note that self.dm_password is None for ADTrustInstance because
|
|
+ # we ensure to be called as root and using ldapi to use autobind
|
|
try:
|
|
self.ldap_enable('ADTRUST', self.fqdn, self.dm_password, \
|
|
self.suffix)
|
|
@@ -449,7 +450,7 @@ class ADTRUSTInstance(service.Service):
|
|
root_logger.info("EXTID Service startup entry already exists.")
|
|
|
|
def __setup_sub_dict(self):
|
|
- self.sub_dict = dict(REALM = self.realm_name,
|
|
+ self.sub_dict = dict(REALM = self.realm,
|
|
SUFFIX = self.suffix,
|
|
NETBIOS_NAME = self.netbios_name,
|
|
SMB_DN = self.smb_dn,
|
|
@@ -460,16 +461,16 @@ class ADTRUSTInstance(service.Service):
|
|
rid_base, secondary_rid_base, no_msdcs=False, smbd_user="samba"):
|
|
self.fqdn = fqdn
|
|
self.ip_address = ip_address
|
|
- self.realm_name = realm_name
|
|
+ self.realm = realm_name
|
|
self.domain_name = domain_name
|
|
self.netbios_name = netbios_name
|
|
self.rid_base = rid_base
|
|
self.secondary_rid_base = secondary_rid_base
|
|
self.no_msdcs = no_msdcs
|
|
self.smbd_user = smbd_user
|
|
- self.suffix = ipautil.realm_to_suffix(self.realm_name)
|
|
+ self.suffix = ipautil.realm_to_suffix(self.realm)
|
|
self.ldapi_socket = "%%2fvar%%2frun%%2fslapd-%s.socket" % \
|
|
- realm_to_serverid(self.realm_name)
|
|
+ realm_to_serverid(self.realm)
|
|
|
|
self.smb_conf = "/etc/samba/smb.conf"
|
|
|
|
@@ -479,7 +480,7 @@ class ADTRUSTInstance(service.Service):
|
|
self.trust_dn = str(DN(api.env.container_trusts, self.suffix))
|
|
self.smb_dom_dn = str(DN(('cn', self.domain_name),
|
|
api.env.container_cifsdomains, self.suffix))
|
|
- self.cifs_principal = "cifs/" + self.fqdn + "@" + self.realm_name
|
|
+ self.cifs_principal = "cifs/" + self.fqdn + "@" + self.realm
|
|
self.cifs_agent = str(DN(('krbprincipalname', self.cifs_principal.lower()),
|
|
api.env.container_service,
|
|
self.suffix))
|
|
@@ -522,11 +523,11 @@ class ADTRUSTInstance(service.Service):
|
|
"range.\nAdd local ID range manually and try " \
|
|
"again!")
|
|
|
|
- entry = ipaldap.Entry(str(DN(('cn', ('%s_id_range' % self.realm_name)),
|
|
+ entry = ipaldap.Entry(str(DN(('cn', ('%s_id_range' % self.realm)),
|
|
api.env.container_ranges,
|
|
self.suffix)))
|
|
entry.setValue('objectclass', 'ipaDomainIDRange')
|
|
- entry.setValue('cn', ('%s_id_range' % self.realm_name))
|
|
+ entry.setValue('cn', ('%s_id_range' % self.realm))
|
|
entry.setValue('ipaBaseID', str(base_id))
|
|
entry.setValue('ipaIDRangeSize', str(id_range_size))
|
|
self.admin_conn.addEntry(entry)
|
|
diff --git a/ipaserver/install/bindinstance.py b/ipaserver/install/bindinstance.py
|
|
index c348cdbb278f222dfbc034cbe1220df26262cb9d..f320202eaa20fc5e8cf1e61ad11a769a4436ba47 100644
|
|
--- a/ipaserver/install/bindinstance.py
|
|
+++ b/ipaserver/install/bindinstance.py
|
|
@@ -448,7 +448,7 @@ class DnsBackup(object):
|
|
|
|
class BindInstance(service.Service):
|
|
def __init__(self, fstore=None, dm_password=None):
|
|
- service.Service.__init__(self, "named", dm_password=dm_password)
|
|
+ service.Service.__init__(self, "named", dm_password=dm_password, ldapi=False, autobind=service.DISABLED)
|
|
self.dns_backup = DnsBackup(self)
|
|
self.named_user = None
|
|
self.domain = None
|
|
diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
|
|
index 2644689a0bc18fdb97d1e66d3f929af24cd101ba..dc4374ccef4f7bd64edb14d77efe35b46895bfb5 100644
|
|
--- a/ipaserver/install/cainstance.py
|
|
+++ b/ipaserver/install/cainstance.py
|
|
@@ -225,10 +225,9 @@ def get_outputList(data):
|
|
|
|
class CADSInstance(service.Service):
|
|
def __init__(self, host_name=None, realm_name=None, domain_name=None, dm_password=None):
|
|
- service.Service.__init__(self, "pkids")
|
|
+ service.Service.__init__(self, "pkids", dm_password=dm_password, ldapi=False, autobind=service.DISABLED)
|
|
self.serverid = "PKI-IPA"
|
|
self.realm_name = realm_name
|
|
- self.dm_password = dm_password
|
|
self.sub_dict = None
|
|
self.domain = domain_name
|
|
self.fqdn = host_name
|
|
diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py
|
|
index 25c449a6e865de01d789a739b31906cb70c6f212..9f3ae7252e45ab3289a85711a2b1202bbe04e137 100644
|
|
--- a/ipaserver/install/dsinstance.py
|
|
+++ b/ipaserver/install/dsinstance.py
|
|
@@ -160,7 +160,7 @@ info: IPA V2.0
|
|
|
|
class DsInstance(service.Service):
|
|
def __init__(self, realm_name=None, domain_name=None, dm_password=None, fstore=None):
|
|
- service.Service.__init__(self, "dirsrv", dm_password=dm_password)
|
|
+ service.Service.__init__(self, "dirsrv", dm_password=dm_password, ldapi=False, autobind=service.DISABLED)
|
|
self.realm_name = realm_name
|
|
self.sub_dict = None
|
|
self.domain = domain_name
|
|
diff --git a/ipaserver/install/krbinstance.py b/ipaserver/install/krbinstance.py
|
|
index 2faf8e19693f891f28838df967399f0bfe2b51a4..8cc50fba4b0ba8d760cc892a624bd64ef09541a6 100644
|
|
--- a/ipaserver/install/krbinstance.py
|
|
+++ b/ipaserver/install/krbinstance.py
|
|
@@ -178,7 +178,7 @@ class KrbInstance(service.Service):
|
|
self.start_creation("Configuring Kerberos KDC", 30)
|
|
|
|
self.kpasswd = KpasswdInstance()
|
|
- self.kpasswd.create_instance('KPASSWD', self.fqdn, self.admin_password, self.suffix)
|
|
+ self.kpasswd.create_instance('KPASSWD', self.fqdn, self.admin_password, self.suffix, realm=self.realm)
|
|
|
|
def create_replica(self, realm_name,
|
|
master_fqdn, host_name,
|
|
diff --git a/ipaserver/install/service.py b/ipaserver/install/service.py
|
|
index 5c2699e3fa4c115c972528d4c2cc6aa170711837..198cb387011be1239eedbff410863232922a21e1 100644
|
|
--- a/ipaserver/install/service.py
|
|
+++ b/ipaserver/install/service.py
|
|
@@ -35,6 +35,11 @@ from ipapython.ipa_log_manager import *
|
|
|
|
CACERT = "/etc/ipa/ca.crt"
|
|
|
|
+# Autobind modes
|
|
+AUTO = 1
|
|
+ENABLED = 2
|
|
+DISABLED = 3
|
|
+
|
|
# 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 = {
|
|
@@ -55,13 +60,14 @@ def print_msg(message, output_fd=sys.stdout):
|
|
|
|
|
|
class Service(object):
|
|
- def __init__(self, service_name, sstore=None, dm_password=None, ldapi=False):
|
|
+ def __init__(self, service_name, sstore=None, dm_password=None, ldapi=True, autobind=AUTO):
|
|
self.service_name = service_name
|
|
self.service = ipaservices.service(service_name)
|
|
self.steps = []
|
|
self.output_fd = sys.stdout
|
|
self.dm_password = dm_password
|
|
self.ldapi = ldapi
|
|
+ self.autobind = autobind
|
|
|
|
self.fqdn = socket.gethostname()
|
|
self.admin_conn = None
|
|
@@ -77,12 +83,44 @@ class Service(object):
|
|
self.dercert = None
|
|
|
|
def ldap_connect(self):
|
|
- if self.ldapi:
|
|
- if not self.realm:
|
|
- raise RuntimeError('realm must be set to use ldapi connection')
|
|
- self.admin_conn = self.__get_conn(None, None, ldapi=True, realm=self.realm)
|
|
- else:
|
|
- self.admin_conn = self.__get_conn(self.fqdn, self.dm_password)
|
|
+ # If DM password is provided, we use it
|
|
+ # If autobind was requested, attempt autobind when root and ldapi
|
|
+ # If autobind was disabled or not succeeded, go with GSSAPI
|
|
+ # LDAPI can be used with either autobind or GSSAPI
|
|
+ # LDAPI requires realm to be set
|
|
+ try:
|
|
+ if self.ldapi:
|
|
+ if not self.realm:
|
|
+ raise errors.NotFound(reason="realm is missing for %s" % (self))
|
|
+ conn = ipaldap.IPAdmin(ldapi=self.ldapi, realm=self.realm)
|
|
+ else:
|
|
+ conn = ipaldap.IPAdmin(self.fqdn, port=389)
|
|
+ if self.dm_password:
|
|
+ conn.do_simple_bind(bindpw=self.dm_password)
|
|
+ elif self.autobind in [AUTO, ENABLED]:
|
|
+ if os.getegid() == 0 and self.ldapi:
|
|
+ try:
|
|
+ # autobind
|
|
+ pw_name = pwd.getpwuid(os.geteuid()).pw_name
|
|
+ conn.do_external_bind(pw_name)
|
|
+ except errors.NotFound, e:
|
|
+ if self.autobind == AUTO:
|
|
+ # Fall back
|
|
+ conn.do_sasl_gssapi_bind()
|
|
+ else:
|
|
+ # autobind was required and failed, raise
|
|
+ # exception that it failed
|
|
+ raise e
|
|
+ else:
|
|
+ conn.do_sasl_gssapi_bind()
|
|
+ else:
|
|
+ conn.do_sasl_gssapi_bind()
|
|
+ except Exception, e:
|
|
+ root_logger.debug("Could not connect to the Directory Server on %s: %s" % (self.fqdn, str(e)))
|
|
+ raise e
|
|
+
|
|
+ self.admin_conn = conn
|
|
+
|
|
|
|
def ldap_disconnect(self):
|
|
self.admin_conn.unbind()
|
|
@@ -93,7 +131,6 @@ class Service(object):
|
|
pw_name = None
|
|
fd = None
|
|
path = ipautil.SHARE_DIR + ldif
|
|
- hostname = installutils.get_fqdn()
|
|
nologlist=[]
|
|
|
|
if sub_dict is not None:
|
|
@@ -107,15 +144,25 @@ class Service(object):
|
|
if sub_dict.has_key('RANDOM_PASSWORD'):
|
|
nologlist.append(sub_dict['RANDOM_PASSWORD'])
|
|
|
|
+ args = ["/usr/bin/ldapmodify", "-v", "-f", path]
|
|
+
|
|
+ # As we always connect to the local host,
|
|
+ # use URI of admin connection
|
|
+ if not self.admin_conn:
|
|
+ self.ldap_connect()
|
|
+ args += ["-H", self.admin_conn._uri]
|
|
+
|
|
+ auth_parms = []
|
|
if self.dm_password:
|
|
[pw_fd, pw_name] = tempfile.mkstemp()
|
|
os.write(pw_fd, self.dm_password)
|
|
os.close(pw_fd)
|
|
auth_parms = ["-x", "-D", "cn=Directory Manager", "-y", pw_name]
|
|
else:
|
|
- auth_parms = ["-Y", "GSSAPI"]
|
|
+ # always try GSSAPI auth when not using DM password or not being root
|
|
+ if os.getegid() != 0:
|
|
+ auth_parms = ["-Y", "GSSAPI"]
|
|
|
|
- args = ["/usr/bin/ldapmodify", "-h", hostname, "-v", "-f", path]
|
|
args += auth_parms
|
|
|
|
try:
|
|
@@ -181,8 +228,19 @@ class Service(object):
|
|
This server cert should be in DER format.
|
|
"""
|
|
|
|
- if not self.admin_conn:
|
|
- self.ldap_connect()
|
|
+ # add_cert_to_service() is relatively rare operation
|
|
+ # we actually call it twice during ipa-server-install, for different
|
|
+ # instances: ds and cs. Unfortunately, it may happen that admin
|
|
+ # connection was created well before add_cert_to_service() is called
|
|
+ # If there are other operations in between, it will become stale and
|
|
+ # since we are using SimpleLDAPObject, not ReconnectLDAPObject, the
|
|
+ # action will fail. Thus, explicitly disconnect and connect again.
|
|
+ # Using ReconnectLDAPObject instead of SimpleLDAPObject was considered
|
|
+ # but consequences for other parts of the framework are largely
|
|
+ # unknown.
|
|
+ if self.admin_conn:
|
|
+ self.ldap_disconnect()
|
|
+ self.ldap_connect()
|
|
|
|
dn = "krbprincipalname=%s,cn=services,cn=accounts,%s" % (self.principal, self.suffix)
|
|
mod = [(ldap.MOD_ADD, 'userCertificate', self.dercert)]
|
|
@@ -268,33 +326,6 @@ class Service(object):
|
|
|
|
self.steps = []
|
|
|
|
- def __get_conn(self, fqdn, dm_password, ldapi=False, realm=None):
|
|
- # If we are passed a password we'll use it as the DM password
|
|
- # otherwise we'll do a GSSAPI bind.
|
|
- try:
|
|
-# conn = ipaldap.IPAdmin(fqdn, port=636, cacert=CACERT)
|
|
- if ldapi:
|
|
- conn = ipaldap.IPAdmin(ldapi=ldapi, realm=realm)
|
|
- else:
|
|
- conn = ipaldap.IPAdmin(fqdn, port=389)
|
|
- if dm_password:
|
|
- conn.do_simple_bind(bindpw=dm_password)
|
|
- elif os.getegid() == 0 and self.ldapi:
|
|
- try:
|
|
- # autobind
|
|
- pw_name = pwd.getpwuid(os.geteuid()).pw_name
|
|
- conn.do_external_bind(pw_name)
|
|
- except errors.NotFound:
|
|
- # Fall back
|
|
- conn.do_sasl_gssapi_bind()
|
|
- else:
|
|
- conn.do_sasl_gssapi_bind()
|
|
- except Exception, e:
|
|
- root_logger.debug("Could not connect to the Directory Server on %s: %s" % (fqdn, str(e)))
|
|
- raise e
|
|
-
|
|
- return conn
|
|
-
|
|
def ldap_enable(self, name, fqdn, dm_password, ldap_suffix):
|
|
self.disable()
|
|
if not self.admin_conn:
|
|
@@ -318,11 +349,14 @@ class Service(object):
|
|
raise e
|
|
|
|
class SimpleServiceInstance(Service):
|
|
- def create_instance(self, gensvc_name=None, fqdn=None, dm_password=None, ldap_suffix=None):
|
|
+ def create_instance(self, gensvc_name=None, fqdn=None, dm_password=None, ldap_suffix=None, realm=None):
|
|
self.gensvc_name = gensvc_name
|
|
self.fqdn = fqdn
|
|
self.dm_password = dm_password
|
|
self.suffix = ldap_suffix
|
|
+ self.realm = realm
|
|
+ if not realm:
|
|
+ self.ldapi = False
|
|
|
|
self.step("starting %s " % self.service_name, self.__start)
|
|
self.step("configuring %s to start on boot" % self.service_name, self.__enable)
|
|
--
|
|
1.7.11.2
|
|
|