ManageIQ/manageiq-smartstate

View on GitHub
lib/metadata/linux/LinuxInitProcs.rb

Summary

Maintainability
C
1 day
Test Coverage
F
17%
require 'manageiq/gems/pending'
require 'util/miq-hash_struct'
require 'util/miq-xml'
require 'metadata/linux/InitProcHash'

module MiqLinux
  class InitProcs
    INIT_DIRS   = ["/etc/rc.d/init.d", "/etc/init.d"]
    RC_DIRS     = ["/etc/rc.d", "/etc", "/etc/init.d"]
    RC_CHECK    = ["rc0.d", "runlevels"]
    RUN_LEVELS1 = ['0', '1', '2', '3', '4', '5', '6', 'S']
    RUN_LEVELS2 = ['boot', 'default', 'network', 'single']

    def initialize(fs)
      @fs = fs
      @scriptsByName = {}

      #
      # Try to determine where the system's init.d directory is.
      #
      $log.debug "Determining init script directory..."
      @init_dir = nil
      INIT_DIRS.each do |id|
        $log.debug "\tChecking: #{id}"
        next unless @fs.fileExists?(id)
        $log.debug "\tFound init script directory: #{id}"
        @init_dir = id
        break
      end
      unless @init_dir
        $log.warn "Could not determine init script directory."
        return
      end

      #
      # Try to determine where the system keeps its runlevel scripts.
      # NOTE: Gentoo is a special case. It uses "named" runlevel directories
      # under the directory "runlevels". As opposed to rc?.d directories.
      #
      $log.debug "Determining RC script directory..."
      @rc_dir = nil
      @rc_chk = nil
      RC_DIRS.each do |rd|
        $log.debug "\tChecking: #{rd}"
        next unless @fs.fileExists?(rd)

        RC_CHECK.each do |rcc|
          next unless @fs.fileExists?(File.join(rd, rcc))
          @rc_chk = rcc
          break
        end
        break unless @rc_chk

        $log.debug "\tFound init script directory: #{rd} - checked: #{@rc_chk}"
        @rc_dir = rd
        break
      end
      unless @rc_dir
        $log.warn "Could not determine RC script directory."
        return
      end

      @fs.dirForeach(@init_dir) do |fn|
        next if @fs.fileDirectory?(File.join(@init_dir, fn))
        name = @fs.fileBasename(fn, ".sh")
        next if name.downcase == "readme" || name == "." || name == ".."

        addScript(@init_dir, fn, name)
      end

      if @rc_chk == "runlevels"
        @rc_dir = File.join(@rc_dir, @rc_chk)
        @run_levels = RUN_LEVELS2
      else
        @run_levels = RUN_LEVELS1
      end

      @run_levels.each do |rl|
        if @rc_chk == "runlevels"
          rld = File.join(@rc_dir, rl)
        else
          rld = File.join(@rc_dir, "rc#{rl}.d")
        end

        next unless @fs.fileDirectory?(rld)
        @fs.dirForeach(rld) do |fn|
          # If it's not a start of kill script, skip it.
          next if fn[0, 1] != "S" && fn[0, 1] != "K" && @rc_chk != "runlevels"
          # Full path to file.
          fp = File.join(rld, fn)
          # If the file isn't a symbolic link, skip it.
          next unless @fs.fileSymLink?(fp)
          lp = @fs.getLinkPath(fp)

          # The init.d script to which the file is linked.
          name = @fs.fileBasename(lp, ".sh")

          addScript(@fs.fileDirname(lp), @fs.fileBasename(lp), name) unless @scriptsByName[name]

          sk = (@rc_chk == "runlevels" ? 'S' : fn[0, 1])
          @scriptsByName[name].runLevels[sk] << rl
        end
      end
    end

    def addScript(dir, fn, name)
      s = MiqHashStruct.new
      s.name = name
      s.path = File.join(dir, fn)
      s.desc = getDesc(s.path, name)
      s.runLevels = Hash.new
      s.runLevels['S'] = []
      s.runLevels['K'] = []
      @scriptsByName[name] = s
    end

    def toXml(doc = nil)
      doc = MiqXml.createDoc(nil) unless doc

      @scriptsByName.each_value do |s|
        ip = doc.add_element("service", "name" => s.name, "image_path" => s.path, "typename" => "linux_initprocess")
        ip.attributes["description"] = s.desc if s.desc

        s.runLevels['S'].each { |rl| ip.add_element("enable_run_level", "value" => rl) }
        s.runLevels['K'].each { |rl| ip.add_element("disable_run_level", "value" => rl) }
      end
    end

    private

    def getDesc(f, n)
      fdata = ""
      begin
        @fs.fileOpen(f) { |fo| fdata = fo.read }
        fdata.each_line { |fl| return $1 if fl =~ /^\s*#\s+Short-Description:\s*(.*)$/ } unless fdata.nil?
        return InitProcHash[n]
      rescue => err
        $log.warn "getDesc: could not open #{f} - #{err}"
        return ""
      end
    end
  end # class InitProcs
end # module MiqLinux