SUSE
index
/usr/lib/sca/python/SUSE.py

Supportconfig Analysis Library for SUSE python patterns
 
Library of functions for creating python patterns specific to SUSE

 
Modules
       
Core
ast
datetime
re

 
Classes
       
PatchInfo

 
class PatchInfo
    A class to retrieve patch information by patch name. The first patch name that matches the search string will be used for the patch information.
 
Variables
---------
search_name = (String) The string used to find the patch from the name column
patch_name = (String) The exact patch name string found in the name column
patch_count = (Int) The number of patches that match patch_name
installed = (Boolean) True if at least one patch is installed in the patch_name set, otherwise False
all_installed = (Boolean) True if all patches in the patch_name set are installed, otherwise False
needed = (Boolean) True if at least one patch is needed in the patch_name set, otherwise False
valid = (Boolean) True if a valid updates.txt section with patch information was found, otherwise False
patchlist = (List of Dictionaries) The dictionary keys correspond to the 'zypper patches' or 'rug pch' output columns with the exception of Installed
        Dictionary Keys:
                Category (String) The patch category like security or recommended
                Status (String) The patch status including Installed, NotApplicable, Applied, Needed, etc.
                Catalog (String) The catalog from which the patch came
                Version (String) The patch's version number string
                Name (String) The name of the patch
                Installed (Boolean) True if the patch is installed or applied, otherwise False
 
Example:
 
import Core
import SUSE
 
DEBUG = False
PATCH = SUSE.PatchInfo('slessp3-kernel')
if( DEBUG ):
        PATCH.debugPatchDisplay()
if( PATCH.valid ):
        if( PATCH.all_installed ):
                Core.updateStatus(Core.IGNORE, "Patches have been applied")
        else:
                Core.updateStatus(Core.WARN, "Update server to apply missing kernel patches")
else:
        Core.updateStatus(Core.ERROR, "ERROR: Invalid patch updates.txt section")
 
  Methods defined here:
__init__(self, search_name)
debugPatchDisplay(self)
Prints the entire list of dictionaries and the class variables. Used for debug purposes only.
getLastInstalled(self)
Returns a dictionary of the last installed patch in the patch_name set based on the version string
getLastNeeded(self)
Returns a dictionary of the last needed patch in the patch_name set based on the version string

Data and other attributes defined here:
patchCount = 0

 
Functions
       
compareKernel(kernelVersion)
Checks if kernel version is newer then given version
Args:           kernelVersion - The kernel version string to compare
Returns:        -1, 0, 1
                                -1      if Installed kernel version older than kernelVerion
                                0       if Installed kernel version equals kernelVerion
                                1       if Installed kernel version newer than kernelVerion
Example:
 
KERNEL_VERSION = '3.0.93'
INSTALLED_VERSION = SUSE.compareKernel(KERNEL_VERSION)
if( INSTALLED_VERSION < 0 ):
        Core.updateStatus(Core.CRIT, "Bug detected in kernel version " + KERNEL_VERSION + " or before, update server for fixes")
else:
        Core.updateStatus(Core.IGNORE, "Bug fixes applied for " + KERNEL_VERSION)
compareRPM(package, versionString)
Compares the versionString to the installed package's version
 
Args:           package - RPM package name
                        versionString - RPM package version string to compare against
Returns:        -1, 0, 1
                                -1      if RPM_NAME older than RPM_VERSION
                                0       if RPM_NAME equals RPM_VERSION
                                1       if RPM_NAME newer than RPM_VERSION
Example:
 
RPM_NAME = 'mypackage'
RPM_VERSION = '1.1.0'
if( SUSE.packageInstalled(RPM_NAME) ):
        INSTALLED_VERSION = SUSE.compareRPM(RPM_NAME, RPM_VERSION)
        if( INSTALLED_VERSION <= 0 ):
                Core.updateStatus(Core.CRIT, "Bug detected in " + RPM_NAME + ", update server for fixes")
        else:
                Core.updateStatus(Core.IGNORE, "Bug fixes applied for " + RPM_NAME)
else:
        Core.updateStatus(Core.ERROR, "ERROR: RPM package not installed: " + RPM_NAME)
getBasicFIPSData()
Returns a dictionary of state of key FIPS data values.
Supportconfigs from SLE12 minimum required
 
Args:                   None
Returns:        Dictionary
Keys:
        Installed = FIPS packages are installed
        Enabled   = FIPS is enabled per /proc/sys/crypto/fips_enabled
        GrubFips  = fips=1 found in /etc/default/grub for GRUB2
        GrubBoot  = boot= found in /etc/default/grub for GRUB2
        KernFips  = fips=1 found in /proc/cmdline
        KernBoot  = boot= found in /proc/cmdline
        Initrd    = fips module included in the ramdisk of the running kernel
                                                        Note: This key is present only if the supportconfig has the lsinitrd output in boot.txt
 
Example:
 
FIPS = SUSE.getBasicFIPSData()
if( FIPS['Installed'] ):
        Core.updateStatus(Core.IGNORE, "FIPS installed")
else:           
        Core.updateStatus(Core.REC, "Consider installing FIPS")
getBasicVirtualization()
      Gathers Virtualization section of the basic-environment.txt file.
 
      Args:                   None
      Returns:        Dictionary
 
      Converts the basic-environment.txt section from this:
 
      #==[ System ]=======================================#
      # Virtualization
      Manufacturer:  HP
      Hardware:      ProLiant DL380 Gen9
      Hypervisor:    None
      Identity:      Not Detected
 
      to this dictionary:
 
{'Hardware': 'ProLiant DL380 Gen9', 'Hypervisor': 'None', 'Identity': 'Not Detected', 'Manufacturer': 'HP'} 
 
      Example:
      SYSTEM = SUSE.getBasicVirtualization()
      if "hp" in SYSTEM['Manufacturer'].lower():
              Core.updateStatus(Core.WARN, "Detected HP hardware")
      else:
              Core.updateStatus(Core.IGNORE, "No HP hardware found")
getConfigFileLVM(PART)
Returns a dictionary of the /etc/lvm/lvm.conf file from the lvm.txt file in supportconfig.
 
Args:                   PART
        If PART is set to '' or 'all', the entire lvm.conf file will be returned in a dictionary of dictionaries.
        If PART is set to a specific lvm.conf section, like 'log' or 'activation', only that section will be returned as a dictionary.
        If PART is set, but not found among the lvm.conf sections, an empty dictionary is returned.
Returns:        Dictionary
Keys:                   Returned from the lvm.conf itself
 
Example 1:
LVM_CONFIG = SUSE.getConfigFileLVM('log')
if( int(LVM_CONFIG['verbose']) > 0 ):
        Core.updateStatus(Core.WARN, "LVM logging set to greater verbosity")
else:           
        Core.updateStatus(Core.IGNORE, "LMV logging is not verbose")
 
Example 2:
LVM_CONFIG = SUSE.getConfigFileLVM('ALL')
if( int(LVM_CONFIG['log']['verbose']) > 0 ):
        Core.updateStatus(Core.WARN, "LVM logging set to greater verbosity")
else:           
        Core.updateStatus(Core.IGNORE, "LMV logging is not verbose")
getDriverInfo(DRIVER_NAME)
Gets information about the specified kernel driver
 
Args:           DRIVER_NAME - The kernel driver name on which you want details
Returns:        Dictionary with keys
                                name (String) - The kernel driver name
                                loaded (Boolean) - True if loaded, otherwise False
                                filename (String) - The driver filename
                                version (String) - The driver's version string
                                license (String) - The driver's license string
                                description (String) - Description of the driver
                                srcversion (String) - The driver's source version
                                supported (String) - Support status string, usually yes or no
                                vermagic (String) - Version magic string
Example:
 
DRIVER_NAME = 'zapi'
DRIVER_INFO = SUSE.getDriverInfo(DRIVER_NAME)
if( DRIVER_INFO['loaded'] ):
        Core.updateStatus(STATUS_IGNORE, "Package " + RPM_INFO['name'] + str(RPM_INFO['version']) + " is installed")
else:
        Core.updateStatus(STATUS_WARNING, "Package " + RPM_INFO['name'] + str(RPM_INFO['version']) + " is missing, install it")
getFileSystems()
Gets all fields from the mounted and unmountd file systems with their associated fstab file and df command output.
 
Args:                   None
Returns:        List of Dictionaries
Keys:
        ActiveDevice  = The active device path
        MountedDevice = The device path from the mount command
        FstabDevice   = The device path from /etc/fstab
        MountPoint    = The mount point
        Type          = File system type
        MountOptions  = Options used when mounted as shown by the mount command
        FstabOptions  = Options defined in the /etc/fstab
        Dump          = /etc/fstab dump field, '' if unknown
        fsck          = /etc/fstab fsck field, '' if unknown
        Mounted       = False = Not mounted, True = Mounted
        Size          = File system size in bytes, '' if unknown
        UsedSpace     = File system space used in bytes, '' if unknown
        AvailSpace    = file system space available in bytes, '' if unknown
        PercentUsed   = file system percent used, -1 if unknown
 
Example:
UNMOUNTED = []
FSLIST = SUSE.getFileSystems()
for FS in FSLIST:
        if( not FS['Mounted'] ):
                UNMOUNTED.append(FS['MountPoint'])
if( UNMOUNTED ):
        Core.updateStatus(Core.WARN, "Detected unmounted filesystems: " + ' '.join(UNMOUNTED))
else:
        Core.updateStatus(Core.IGNORE, "All filesystems appear to be mounted")
getGrub2Config()
Returns a dictionary of the key/value pairs found in /etc/default/grub.
Supportconfigs from SLE12 minimum required
 
Args:                   None
Returns:        Dictionary
Keys:                   As defined in /etc/default/grub. All keys are forced to uppercase, values are left as is.
 
Example:
 
CONFIG = SUSE.getGrub2Config()
if( "splash=silent" in CONFIG['GRUB_CMDLINE_LINUX_DEFAULT'].lower() ):
        Core.updateStatus(Core.REC, "Use splash=native for more screen output")
else:
        Core.updateStatus(Core.IGNORE, "Additional screen output ignored")
getHostInfo()
Gets information about the server
 
Args:           None
Returns:        Dictionary with keys
        Hostname (String) - The hostname of the server analyzed
        KernelVersion (String) - The running kernel version
        Architecture (String)
        Distro (String) - The name of the distribution
        DistroVersion (Int) - The major distribution version number
        DistroPatchLevel (Int) - The distribution service patch level
Example:
 
import re
SERVER = SUSE.getHostInfo()
SLE = re.compile("SUSE Linux Enterprise Server", re.IGNORECASE)
if SLE.search(SERVER['Distro']):
        if( SERVER['DistroVersion'] >= 11 and SERVER['DistroVersion'] < 12 ):
                Core.updateStatus(Core.WARN, "SLES" + str(SERVER['DistroVersion']) + "SP" + str(SERVER['DistroPatchLevel']) + ": Testing required")
        else:
                Core.updateStatus(Core.IGNORE, "SLES" + str(SERVER['DistroVersion']) + "SP" + str(SERVER['DistroPatchLevel']) + ": No Testing Needed")
else:
        Core.updateStatus(Core.ERROR, SERVER['Distro'] + ": Invalid Distribution for Test Case")
getProcCmdLine()
Gathers the /proc/cmdline and assigns each value to a list element.
 
Args:                   None
Returns:        List
Example:
 
CMDLINE = SUSE.getProcCmdLine()
CRASH_DEFINED = False
for OPTION in CMDLINE:
        if "crashkernel=" in OPTION:
                CRASH_DEFINED = True
if( CRASH_DEFINED ):
        Core.updateStatus(Core.IGNORE, "Kernel crash memory is defined")
else:
        Core.updateStatus(Core.REC, "Consider configuring the server for a kernel core dump")
getRpmInfo(PackageName)
Retrieves RPM package information from supportconfig files using the specified PackageName
 
Args:           PackageName - RPM package name on which you want details
Returns:        Dictionary with keys
                                name (String) - The RPM package name
                                version (String) - The RPM package version string
                                vendor (String) - The RPM vendor
                                installTime (String) - The date and time the package was installed
Example:
 
RPM_NAME = 'kernel-xen'
RPM_INFO = SUSE.getRpmInfo(RPM_NAME)
if( len(RPM_INFO) > 0 ):
        Core.updateStatus(STATUS_IGNORE, "Package " + RPM_INFO['name'] + str(RPM_INFO['version']) + " is installed")
else:
        Core.updateStatus(STATUS_WARNING, "Package " + RPM_INFO['name'] + str(RPM_INFO['version']) + " is missing, install it")
getSCCInfo()
Gets information provided by the SUSEConnect --status command in SLE12
 
Requires: None
Args:                   None
Returns:        List of Dictionaries
Keys:                   The dictionary key names correspond to the field names from SUSEConnect command. The dictionaries are variable in length.
 
Example:
 
SCC_INFO = SUSE.getSCCInfo()
UNREGISTERED_LIST = []
if( SCC_INFO ):
        for I in range(len(SCC_INFO)):
                if( "registered" != str(SCC_INFO[I]['status'].lower()) ):
                        UNREGISTERED_LIST.append(SCC_INFO[I]['identifier'])
        if( UNREGISTERED_LIST ):
                Core.updateStatus(Core.WARN, "Detected unregistered products: " + str(UNREGISTERED_LIST))
        else:
                Core.updateStatus(Core.IGNORE, "All products appear to be registered")
else:
        Core.updateStatus(Core.ERROR, "ERROR: Missing SUSEConnect Information")
getSCRunTime()
Gets information about when the supportconfig was run
 
Requires: import datetime
Args:                   None
Returns:        datetime object
 
Example:
 
import datetime
SC_RUN_TIME = SUSE.getSCRunTime()
if( SC_RUN_TIME < datetime.datetime.now() - datetime.timedelta(days=30) ):
        Core.updateStatus(Core.WARN, "Supportconfig data are older than 30 days, run a new supportconfig")
else:
        Core.updateStatus(Core.IGNORE, "Supportconfig data are current")
getScInfo()
Gets information about the supportconfig archive itself
 
Args:           None
Returns:        Dictionary with keys
                                envValue (String) - Environment value
                                kernelValue (Integer) - Kernel number based on its version
                                cmdline (String) - Supportconfig's command line arguments
                                config (String) - Supportconfig configuration options
                                version (String) - Supportconfig version
                                scriptDate (String) - Supportconfig script date
Example:
 
REQUIRED_VERSION = '2.25-173';
SC_INFO = SUSE.getSCInfo();
if( Core.compareVersions(SC_INFO['version'], REQUIRED_VERSION) >= 0 ):
        Core.updateStatus(Core.IGNORE, "Supportconfig v" + str(SC_INFO['version']) + " meets minimum requirement")
else:
        Core.updateStatus(Core.WARN, "Supportconfig v" + str(SC_INFO['version']) + " NOT sufficient, " + str(REQUIRED_VERSION) + " or higher needed")
getServiceDInfo(SERVICE_NAME)
Returns a dictionary of systemd service information for SERVICE_NAME
 
Args:           SERVICE_NAME - Name of systemd service
Returns:        Dictionary with keys corresponding to systemctl show SERVICE_NAME
                        output.
Example:
 
SERVICE = 'cups.service'
SERVICE_INFO = SUSE.getServiceDInfo(SERVICE)
if( SERVICE_INFO['SubState'] == 'running' ):
        Core.updateStatus(Core.IGNORE, "Service is running: " + str(SERVICE_NAME));
else:
        Core.updateStatus(Core.WARN, "Service is down: " + str(SERVICE_NAME));
getServiceInfo(SERVICE_NAME)
Returns a dictionary of system service information for SERVICE_NAME
 
Args:           SERVICE_NAME - Name of System V service
Returns:        Dictionary with keys
                                Name (String) - System V service name
                                Running (Integer) - -1=Unknown, 0=Unused or Dead, 1=Running
                                BootLevels (String) - A list of runlevel numbers in which the service is 
                                        turned on for boot. An empty string means the service is turned off at
                                        boot for all runlevels.
                                RunLevel (String) - The current system runlevel
                                OnForRunLevel (Bool) - False=Service is turned off for the current runlevel, True=Service is turned on for the current runlevel
                                Known (Bool) - True=The service is found in the service table, False=The service is not known and only partial information may be included.
Example:
 
SERVICE = 'cups'
SERVICE_INFO = SUSE.getServiceInfo(SERVICE)
if( SERVICE_INFO['Running'] > 0 ):
        Core.updateStatus(Core.IGNORE, "Service is running: " + str(SERVICE_NAME));
else:
        Core.updateStatus(Core.WARN, "Service is down: " + str(SERVICE_NAME));
getZypperProductList()
Gathers zypper products output into a list of dictionaries
 
Args:                   None
Returns:        List of Dictionaries
Keys:                   The dictionary key names correspond to the field names from zypper products command.
                                        Status (S) - Product status
                                        Repository
                                        InternalName
                                        Name
                                        Version
                                        Architecture (Arch)
                                        IsBase - True (Yes) is the product is a base product, otherwise False (No).
 
Example:
 
PRODUCT_LIST = SUSE.getZypperProductList()
BASE_PRODUCTS = []
for I in range(len(PRODUCT_LIST)):
        if( PRODUCT_LIST[I]['IsBase'] ):
                BASE_PRODUCTS.append(PRODUCT_LIST[I]['Name'])
if( BASE_PRODUCTS ):
        Core.updateStatus(Core.SUCC, "Base products found: " + str(BASE_PRODUCTS))
else:
        Core.updateStatus(Core.CRIT, "No base products found")
getZypperRepoList()
Gathers zypper repos output into a list of dictionaries
 
Args:                   None
Returns:        List of Dictionaries
Keys:                   The dictionary key names correspond to the field names from zypper repos command.
                                        Num - Repository number
                                        Alias
                                        Name
                                        Enabled - True (Yes) if the repository is enabled, otherwise False (No).
                                        Refresh - True (Yes) is the repository is set to refresh, otherwise False (No).
 
Example:
 
REPO_LIST = SUSE.getZypperRepoList()
DISABLED_REPOS = []
for I in range(len(REPO_LIST)):
        if( not REPO_LIST[I]['Enabled'] ):
                DISABLED_REPOS.append(REPO_LIST[I]['Name'])
if( DISABLED_REPOS ):
        Core.updateStatus(Core.WARN, "Detected " + str(len(DISABLED_REPOS)) + " disabled repositories of " + str(len(REPO_LIST)) + " available: " + str(DISABLED_REPOS))
else:
        Core.updateStatus(Core.IGNORE, "Not disabled repositories detected")
packageInstalled(PackageName)
The PackageName is installed on the server
Args:           PackageName - The RPM package name to check if installed
Returns:        True or False
                                True    PackageName is installed
                                False   PackageName is NOT installed
Example:
 
PACKAGE_NAME = 'bind'
if ( SUSE.packageInstalled(PACKAGE_NAME) ):
        Core.updateStatus(Core.WARN, "The package " + PACKAGE_NAME + " is installed")
else:
        Core.updateStatus(Core.IGNORE, "The package " + PACKAGE_NAME + " is NOT installed")
securityAnnouncementPackageCheck(NAME, MAIN, LTSS, SEVERITY, TAG, PACKAGES)
Specialty function for SUSE Security Announcements (http://lists.opensuse.org/opensuse-security-announce/) that checks the versions of the listed PACKAGES and displays a uniform output string. If any one of the packages listed is less than the fixed version in the PACKAGES dictionary, a hit is triggered. The MAIN is optional. If the MAIN package is installed the other PACKAGES are checked, otherwise no packages are checked. If MAIN is missing, all PACKAGES are checked.
 
Args:           NAME (String) - The display name of the package group being checked
                        MAIN (String) - The MAIN package that must be present as a condition of checking the others; leave blank to check all PACKAGES
                        LTSS (Boolean) - True if an LTSS package, False if not
                        SEVERITY (String) - The severity of the security announcement (ie 'Critical', 'Important', etc)
                        TAG (String) - The specific security announcement tag (ie SUSE-SU-2012:0000-0)
                        PACKAGES (Dictionary) - A dictionary of package names for keys and their fixed version number for values
Returns:        True if at least one from PACKAGES was installed, False if no PACKAGES were installed
Example:
 
LTSS = False
NAME = 'Firefox'
MAIN = 'MozillaFirefox'
SEVERITY = 'Important'
TAG = 'SUSE-SU-2012:0000-0'
PACKAGES = {}
SERVER = SUSE.getHostInfo()
 
if ( SERVER['DistroVersion'] == 11 and SERVER['DistroPatchLevel'] == 3 ):
        PACKAGES = {
                'libfreebl3': '3.16.1-0.8.1',
                'MozillaFirefox': '24.6.0esr-0.8.1',
                'MozillaFirefox-translations': '24.6.0esr-0.8.1',
                'mozilla-nspr': '4.10.6-0.3.1',
                'mozilla-nss': '3.16.1-0.8.1',
        }
        SUSE.securityAnnouncementPackageCheck(NAME, MAIN, LTSS, SEVERITY, TAG, PACKAGES)
else:
        Core.updateStatus(Core.ERROR, "ERROR: " + NAME + " Security Announcement: Outside the distribution scope")
serviceDHealth(SERVICE_NAME)
Reports the health of the specified systemd service
 
Args:           SERVICE_NAME
Returns:        N/A
Example:        
 
PACKAGE = "cups"
SERVICE = "cups.service"
if( SUSE.packageInstalled(PACKAGE) ):
        SUSE.serviceDHealth(SERVICE)
else:
        Core.updateStatus(Core.ERROR, "Basic Service Health; Package Not Installed: " + str(PACKAGE))

 
Data
        SLE10GA = '2.6.16.21-0.8'
SLE10SP0 = '2.6.16.21-0.8'
SLE10SP1 = '2.6.16.46-0.12'
SLE10SP2 = '2.6.16.60-0.21'
SLE10SP3 = '2.6.16.60-0.54.5'
SLE10SP4 = '2.6.16.60-0.85.1'
SLE10SP5 = '2.6.17'
SLE11GA = '2.6.27.19-5'
SLE11SP0 = '2.6.27.19-5'
SLE11SP1 = '2.6.32.12-0.7'
SLE11SP2 = '3.0.13-0.27'
SLE11SP3 = '3.0.76-0.11.1'
SLE11SP4 = '3.0.101-0.63.1'
SLE11SP5 = '3.1'
SLE12GA = '3.12.28-4'
SLE12SP0 = '3.12.28-4'
SLE12SP1 = '3.12.49-11.1'
SLE12SP2 = '3.999'
SLE12SP3 = '3.999'
SLE12SP4 = '3.999'
SLE12SP5 = '3.999'
SLE9GA = '2.6.5-7.97'
SLE9SP0 = '2.6.5-7.97'
SLE9SP1 = '2.6.5-7.139'
SLE9SP2 = '2.6.5-7.191'
SLE9SP3 = '2.6.5-7.244'
SLE9SP4 = '2.6.5-7.308'
SLE9SP5 = '2.6.5-8'
path = ''