Modules development ******************* Basics ====== Langage ------- A module can be implemented in any programing langage : shell scripts, python, perl, C, ... Rules ----- The rules are passed to the modules through environment variables. Advanced langages can use complex serialized variable values like JSON or XML. Parameters ---------- A module must support only one mandatory argument. Its' values can be either .. function:: check parameter Verify the rules are applied on the node or service. .. function:: fixable parameter Verify the module can apply the rules on the service or node. .. function:: fix parameter Apply the rules on the node or service Return code ----------- A module must return one of those three possible values .. function:: return code 0 Compliance checks or fixes passed. .. function:: return code 1 Compliance checks or fixes failed. .. function:: return code 2 Compliance checks or fixes are not applicable. For example when no rules are made available to the module. Location -------- Modules are installed in ``/compliance``. File naming conventions ----------------------- A module can be either a file or a directory tree. The top-level file or directory name must comply to the naming convention: :: [S][0-9]+[-]modname If the module top-level object is a directory, the file tree under it must be either: :: [S][0-9]+[-]modname/main or: :: [S][0-9]+[-]modname/scripts/main Compliance Objects ================== OpenSVC distributes a collection of compliance objects, implemented as executable python classes, to ease module development. They implement common checks and fixes. The skeletons presented below make use of these objects. Objects take complex serialized rules as input, and the collector implements forms to easily create those rules. The calling modules have to specify to the object 2 informations: * The called action : fix, fixable or check * The variable name prefix the object must care about. The object will search the environment for variables matching this prefix. Module skeleton =============== Shell script ------------ :: #!/bin/bash PATH_SCRIPT="$(cd $(/usr/bin/dirname $(type -p -- $0 || echo $0));pwd)" PATH_LIB=$PATH_SCRIPT/com.opensvc PREFIX=OSVC_COMP_FOO typeset -i r=0 case $1 in check) $PATH_LIB/files.py ${PREFIX}_FILES check [ $? -eq 1 ] && r=1 $PATH_LIB/packages.py ${PREFIX}_PKG check [ $? -eq 1 ] && r=1 exit $r ;; fix) $PATH_LIB/files.py ${PREFIX}_FILES check [ $? -eq 1 ] && exit 1 $PATH_LIB/packages.py ${PREFIX}_PKG check [ $? -eq 1 ] && exit 1 ;; fixable) exit 2 ;; esac Python script ------------- :: #!/usr/bin/env python import os import sys sys.path.append(os.path.join(os.path.dirname(__file__), 'com.opensvc')) from comp import * import files import packages syntax = """syntax: %s check|fixable|fix"""%sys.argv[0] if len(sys.argv) != 2: print >>sys.stderr, "wrong number of arguments" print >>sys.stderr, syntax sys.exit(RET_ERR) objs = [] try: o = packages.CompPackages(prefix='OSVC_COMP_BDC_DHCPD_PACKAGE') objs.append(o) except NotApplicable: pass try: o = files.CompFiles(prefix='OSVC_COMP_BDC_DHCPD_FILE') objs.append(o) except NotApplicable: pass def check(): r = 0 for o in objs: r |= o.check() return r def fixable(): return RET_NA def fix(): r = 0 for o in objs: r |= o.fix() return r try: if sys.argv[1] == 'check': RET = check() elif sys.argv[1] == 'fix': RET = fix() elif sys.argv[1] == 'fixable': RET = fixable() else: print >>sys.stderr, "unsupported argument '%s'"%sys.argv[1] print >>sys.stderr, syntax RET = RET_ERR except NotApplicable: sys.exit(RET_NA) except: import traceback traceback.print_exc() sys.exit(RET_ERR) sys.exit(RET)