summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNarayan Desai <desai@mcs.anl.gov>2009-01-23 02:57:34 +0000
committerNarayan Desai <desai@mcs.anl.gov>2009-01-23 02:57:34 +0000
commit154c97c06501ef66e0a103644731ed53d1096fc3 (patch)
treeac1f97249e4209e0dc49a312d87b9b674faa6ee0
parentf7f0b49a8d6e7ffef6690184bf083a678dc2e5fb (diff)
downloadbcfg2-154c97c06501ef66e0a103644731ed53d1096fc3.tar.gz
bcfg2-154c97c06501ef66e0a103644731ed53d1096fc3.tar.bz2
bcfg2-154c97c06501ef66e0a103644731ed53d1096fc3.zip
Simplify service configuration; make all services use common restart framework
git-svn-id: https://svn.mcs.anl.gov/repos/bcfg/trunk/bcfg2@5040 ce84e21b-d406-0410-9b95-82705330c041
-rw-r--r--doc/1.0-roadmap13
-rw-r--r--man/bcfg2.19
-rw-r--r--src/lib/Client/Tools/Chkconfig.py5
-rw-r--r--src/lib/Client/Tools/DebInit.py20
-rw-r--r--src/lib/Client/Tools/FreeBSDInit.py20
-rw-r--r--src/lib/Client/Tools/SMF.py33
-rw-r--r--src/lib/Client/Tools/__init__.py59
-rw-r--r--src/lib/Options.py4
-rwxr-xr-xsrc/sbin/bcfg22
9 files changed, 85 insertions, 80 deletions
diff --git a/doc/1.0-roadmap b/doc/1.0-roadmap
index 1bd0b9df2..2daebb9d5 100644
--- a/doc/1.0-roadmap
+++ b/doc/1.0-roadmap
@@ -22,6 +22,8 @@ server.
** bind failure annotations
** plugin self-bootstrap (get out of bcfg2-admin init)
** core plugin filtering (for bcfg2-admin & co)
+** Change to mode attribute for services
+*** Document
* Pie in the sky
** Rework XMLRPC interfaces
@@ -34,3 +36,14 @@ server.
** Probes
*** switched over to a connector interface
*** data available as metadata.Probes
+** Service changes
+*** Add overall client service mode
+**** default (perform all service manipulations)
+**** disabled (perform no service manipulations)
+**** build (attempt to stop all services started) (deprecates/replaces -B)
+*** Add per service mode
+**** mode='manual' (do not start/stop/restart this service)
+**** mode='default' (perform appropriate service ops)
+**** mode='supervised' (default + ensure service is running when verification is performed)
+ (deprecates supervised='true')
+**** mode='custom' (set non-default restart target in conjunction with target attr)
diff --git a/man/bcfg2.1 b/man/bcfg2.1
index 8a45606a0..936f59e37 100644
--- a/man/bcfg2.1
+++ b/man/bcfg2.1
@@ -1,4 +1,4 @@
-.TH "bcfg2" 1
+ .TH "bcfg2" 1
.SH NAME
bcfg2 \- reconfigure machine based on settings in BCFG2
.SH SYNOPSIS
@@ -20,10 +20,6 @@ state.
Run in agent (continuous) mode, wait for reconfigure command from
server.
.TP
-.BR "\-B"
-Run bcfg2 in build mode. Services aren't started, as the system
-may still be in miniroot.
-.TP
.BR "\-C <configfile>"
Specify alternate bcfg2.conf location
.TP
@@ -56,6 +52,9 @@ configuration files marked as paranoid by the Bcfg2 server.
Specify the number of times that the client will attempt to retry
network communication.
.TP
+.BR "\-s <service mode>"
+Set bcfg2 interaction level for services. Default behavior is to modify all services effected by reconfiguration. build mode attempts to stop all services started. disabled suppresses all attempts to modify services.
+.TP
.BR "\-S https://server:port"
Manually specify the server location (as opposed to using the value in
bcfg2.conf).
diff --git a/src/lib/Client/Tools/Chkconfig.py b/src/lib/Client/Tools/Chkconfig.py
index ae3beaecb..5f867ee2d 100644
--- a/src/lib/Client/Tools/Chkconfig.py
+++ b/src/lib/Client/Tools/Chkconfig.py
@@ -13,6 +13,9 @@ class Chkconfig(Bcfg2.Client.Tools.SvcTool):
__handles__ = [('Service', 'chkconfig')]
__req__ = {'Service': ['name', 'status']}
+ def get_svc_command(self, service, action):
+ return "/sbin/service %s %s" % (service.get('name'), action)
+
def VerifyService(self, entry, _):
'''Verify Service status for entry'''
try:
@@ -44,7 +47,7 @@ class Chkconfig(Bcfg2.Client.Tools.SvcTool):
else:
status = (len(onlevels) == 0)
- if entry.get('supervised', 'false') == 'true':
+ if entry.get('mode', 'default') == 'supervised':
pstatus, pout = self.cmd.run('/sbin/service %s status' % \
entry.get('name'))
if pstatus:
diff --git a/src/lib/Client/Tools/DebInit.py b/src/lib/Client/Tools/DebInit.py
index b18c11cd5..cd5b7c784 100644
--- a/src/lib/Client/Tools/DebInit.py
+++ b/src/lib/Client/Tools/DebInit.py
@@ -7,10 +7,9 @@ import Bcfg2.Client.Tools
class DebInit(Bcfg2.Client.Tools.SvcTool):
'''Debian Service Support for Bcfg2'''
name = 'DebInit'
- __execs__ = ['/usr/sbin/update-rc.d']
+ __execs__ = ['/usr/sbin/update-rc.d', '/usr/sbin/invoke-rc.d']
__handles__ = [('Service', 'deb')]
__req__ = {'Service': ['name', 'status']}
- __svcrestart__ = 'restart'
svcre = re.compile("/etc/.*/(?P<action>[SK])(?P<sequence>\d+)(?P<name>\S+)")
# implement entry (Verify|Install) ops
@@ -94,18 +93,5 @@ class DebInit(Bcfg2.Client.Tools.SvcTool):
# Extra services need to be reflected in the config
return
- def BundleUpdated(self, bundle, states):
- '''The Bundle has been updated'''
- for entry in bundle:
- if self.handlesEntry(entry):
- command = "/usr/sbin/invoke-rc.d %s" % entry.get('name')
- if entry.get('status') == 'on' and not self.setup['build']:
- self.logger.debug('Restarting service %s' % entry.get('name'))
- rc = self.cmd.run('%s %s' % (command, \
- entry.get('reload', self.__svcrestart__)))[0]
- else:
- self.logger.debug('Stopping service %s' % entry.get('name'))
- rc = self.cmd.run('%s stop' % command)[0]
- if rc:
- self.logger.error("Failed to restart service %s" % (entry.get('name')))
-
+ def get_svc_command(self, service, action):
+ return '/usr/sbin/invoke-rc.d %s %s' % (service.get('name'), action)
diff --git a/src/lib/Client/Tools/FreeBSDInit.py b/src/lib/Client/Tools/FreeBSDInit.py
index 4f5131fb5..5837cff37 100644
--- a/src/lib/Client/Tools/FreeBSDInit.py
+++ b/src/lib/Client/Tools/FreeBSDInit.py
@@ -12,25 +12,9 @@ class FreeBSDInit(Bcfg2.Client.Tools.SvcTool):
name = 'FreeBSDInit'
__handles__ = [('Service', 'freebsd')]
__req__ = {'Service': ['name', 'status']}
- __svcrestart__ = 'restart'
def VerifyService(self, entry, _):
return True
- def BundleUpdated(self, bundle, states):
- '''The Bundle has been updated'''
- for entry in bundle:
- if self.handlesEntry(entry):
- command = "/usr/local/etc/rc.d/%s" % entry.get('name')
- if entry.get('status') == 'on' and not self.setup['build']:
- self.logger.debug('Restarting service %s' % \
- entry.get('name'))
- rc = self.cmd.run('%s %s' % (command, \
- entry.get('reload', self.__svcrestart__)))[0]
- else:
- self.logger.debug('Stopping service %s' % entry.get('name'))
- rc = self.cmd.run('%s stop' % command)[0]
- if rc:
- self.logger.error("Failed to restart service %s" % \
- (entry.get('name')))
-
+ def get_svc_command(self, service, action):
+ return "/usr/local/etc/rc.d/%s %s" % (service.get('name'), action)
diff --git a/src/lib/Client/Tools/SMF.py b/src/lib/Client/Tools/SMF.py
index 399418986..bbe9a3055 100644
--- a/src/lib/Client/Tools/SMF.py
+++ b/src/lib/Client/Tools/SMF.py
@@ -4,7 +4,7 @@ __revision__ = '$Revision$'
import glob, os
import Bcfg2.Client.Tools
-class SMF(Bcfg2.Client.Tools.Tool):
+class SMF(Bcfg2.Client.Tools.SvcTool):
'''Support for Solaris SMF Services'''
__handles__ = [('Service', 'smf')]
__execs__ = ['/usr/sbin/svcadm', '/usr/bin/svcs']
@@ -12,6 +12,17 @@ class SMF(Bcfg2.Client.Tools.Tool):
__req__ = {'Service':['name', 'status']}
__ireq__ = {'Service': ['name', 'status', 'FMRI']}
+ def get_svc_command(self, service, action):
+ if service.get('type') == 'lrc':
+ return Bcfg2.Client.Tools.SvcTool.get_svc_command(self,
+ service, action)
+ if action == 'stop':
+ return "/usr/sbin/svcadm disable %s" % (service.get('FMRI'))
+ elif action == 'restart':
+ return "/usr/sbin/svcadm restart %s" % (service.get('FMRI'))
+ elif action == 'start':
+ return "/usr/sbin/svcadm enable %s" % (service.get('FMRI'))
+
def GetFMRI(self, entry):
'''Perform FMRI resolution for service'''
if not 'FMRI' in entry.attrib:
@@ -114,23 +125,3 @@ class SMF(Bcfg2.Client.Tools.Tool):
if svc.get("FMRI") in allsrv]
return [Bcfg2.Client.XML.Element("Service", type='smf', name=name) \
for name in allsrv]
-
- def BundleUpdated(self, bundle, states):
- '''Restart smf services'''
- for entry in [entry for entry in bundle if self.handlesEntry(entry)]:
- if not self.canInstall(entry):
- self.logger.error("Insufficient information to restart service %s" % \
- (entry.get('name')))
- else:
- if entry.get("FMRI").startswith('lrc'):
- if entry.get('status') == 'on':
- self.logger.info("Restarting smf/lrc service %s"%(entry.get("name")))
- self.cmd.run("/etc/init.d/%s %s" % (entry.get('name'),
- entry.get('reload', 'reload')))
- else:
- if entry.get('status') == 'on':
- self.logger.info("Restarting smf service %s" % (entry.get("FMRI")))
- self.cmd.run("/usr/sbin/svcadm restart %s" % (entry.get("FMRI")))
- else:
- self.cmd.run("/usr/sbin/svcadm disable %s" % (entry.get("FMRI")))
-
diff --git a/src/lib/Client/Tools/__init__.py b/src/lib/Client/Tools/__init__.py
index a827e7924..d44356f9b 100644
--- a/src/lib/Client/Tools/__init__.py
+++ b/src/lib/Client/Tools/__init__.py
@@ -272,7 +272,8 @@ class PkgTool(Tool):
def FindExtraPackages(self):
'''Find extra packages'''
packages = [entry.get('name') for entry in self.getSupportedEntries()]
- extras = [data for data in self.installed.iteritems() if data[0] not in packages]
+ extras = [data for data in self.installed.iteritems() \
+ if data[0] not in packages]
return [Bcfg2.Client.XML.Element('Package', name=name, \
type=self.pkgtype, version=version) \
for (name, version) in extras]
@@ -280,21 +281,47 @@ class PkgTool(Tool):
class SvcTool(Tool):
'''This class defines basic Service behavior'''
name = 'SvcTool'
- __svcrestart__ = 'reload'
+
+ def get_svc_command(self, service, action):
+ '''Return the basename of the command used to start/stop services'''
+ return '/etc/init.d/%s %s' % (service.get('name'), action)
+
+ def start_service(self, service):
+ self.logger.debug('Starting service %s' % service.get('name'))
+ return self.cmd.run(self.get_svc_command(service, 'start'))[0]
+
+ def stop_service(self, service):
+ self.logger.debug('Stopping service %s' % service.get('name'))
+ return self.cmd.run(self.get_svc_command(service, 'stop'))[0]
+
+ def restart_service(self, service):
+ self.logger.debug('Restarting service %s' % service.get('name'))
+ restart_target = 'restart'
+ if service.get('mode', 'default') == 'custom':
+ restart_target = service.get('custom', 'restart')
+ return self.cmd.run(self.get_svc_command(service, restart_target))[0]
+
+ def check_service(self, service):
+ # not supported for this driver
+ return 0
def BundleUpdated(self, bundle, states):
'''The Bundle has been updated'''
- for entry in bundle:
- if self.handlesEntry(entry):
- rc = 0
- if entry.get('status') == 'on' and not self.setup['build']:
- self.logger.debug('Restarting service %s' % entry.get('name'))
- rc = self.cmd.run('/etc/init.d/%s %s' % \
- (entry.get('name'), entry.get('reload', self.__svcrestart__)))[0]
- elif not self.setup['build']:
- self.logger.debug('Stopping service %s' % entry.get('name'))
- rc = self.cmd.run('/etc/init.d/%s stop' % \
- (entry.get('name')))[0]
- if rc:
- self.logger.error("Failed to restart service %s" % \
- (entry.get('name')))
+ if self.setup['servicemode'] == 'disabled':
+ return
+
+ for entry in [ent for ent in bundle if self.handlesEntry(ent)]:
+ if entry.get('mode', 'default') == 'manual':
+ continue
+ # need to handle servicemode = (build|default)
+ # need to handle mode = (default|supervised|custom)
+ if entry.get('status') == 'on':
+ if self.setup['servicemode'] == 'build':
+ rc = self.stop_service(entry)
+ else:
+ rc = self.restart_service(entry)
+ else:
+ rc = self.stop_service(entry)
+ if rc:
+ self.logger.error("Failed to manipulate service %s" % \
+ (entry.get('name')))
diff --git a/src/lib/Options.py b/src/lib/Options.py
index dd9557521..c8716bdeb 100644
--- a/src/lib/Options.py
+++ b/src/lib/Options.py
@@ -232,7 +232,6 @@ CLIENT_KEVLAR = Option('run in kevlar (bulletproof) mode', default=False,
cmd='-k', )
CLIENT_DLIST = Option('run client in server decision list mode', default=False,
cmd='-l', odesc='<whitelist|blacklist>')
-CLIENT_BUILD = Option('run in build mode', default=False, cmd='-B', )
CLIENT_FILE = Option('configure from a file rather than querying the server',
default=False, cmd='-f', odesc='<specification path>')
SERVER_FINGERPRINT = Option('Server Fingerprint', default=[], cmd='-F',
@@ -260,6 +259,9 @@ OMIT_LOCK_CHECK = Option('Omit lock check', default=False, cmd='-O')
LOGGING_FILE_PATH = Option('Set path of file log', default=None, cmd='-o', odesc='<path>', cf=('logging', 'path'))
+CLIENT_SERVICE_MODE = Option('Set client service mode', default='default',
+ cmd='-s', odesc='<default|disabled|build>')
+
class OptionParser(OptionSet):
'''OptionParser bootstraps option parsing, getting the value of the config file'''
def __init__(self, args):
diff --git a/src/sbin/bcfg2 b/src/sbin/bcfg2
index bd05b3a53..0a4092b7f 100755
--- a/src/sbin/bcfg2
+++ b/src/sbin/bcfg2
@@ -98,7 +98,6 @@ class Client:
'drivers': Bcfg2.Options.CLIENT_DRIVERS,
'fingerprint': Bcfg2.Options.SERVER_FINGERPRINT,
'dryrun': Bcfg2.Options.CLIENT_DRYRUN,
- 'build': Bcfg2.Options.CLIENT_BUILD,
'paranoid': Bcfg2.Options.CLIENT_PARANOID,
'bundle': Bcfg2.Options.CLIENT_BUNDLE,
'file': Bcfg2.Options.CLIENT_FILE,
@@ -122,6 +121,7 @@ class Client:
'omit-lock-check': Bcfg2.Options.OMIT_LOCK_CHECK,
'filelog': Bcfg2.Options.LOGGING_FILE_PATH,
'decision': Bcfg2.Options.CLIENT_DLIST,
+ 'servicemode': Bcfg2.Options.CLIENT_SERVICE_MODE,
}
self.setup = Bcfg2.Options.OptionParser(optinfo)