ManageIQ/manageiq-smartstate

View on GitHub
lib/VolumeManager/MiqNativeVolumeManager.rb

Summary

Maintainability
A
4 hrs
Test Coverage
F
13%
require "ostruct"
require "disk/MiqDisk"
require 'binary_struct'
require 'VolumeManager/MiqLvm'

class MiqNativeVolumeManager
  attr_accessor :rootTrees
  attr_reader :logicalVolumes, :physicalVolumes, :visibleVolumes, :hiddenVolumes, :allPhysicalVolumes, :vgHash, :wholeDisks, :diskInitErrors

  def initialize(vmCfg, _ost = nil)
    @logicalVolumes     = []         # visible logical volumes
    @physicalVolumes    = []         # visible physical volumes
    @hiddenVolumes      = []         # hidded volumes (in volume groups)
    @allPhysicalVolumes = []         # all physical volumes
    @wholeDisks         = []         # a list of open base disks
    @visibleVolumes   = nil       # logical and physical volumes that should eb checked for filesystems
    @vgHash             = {}          # volume groups hashed by name
    @lvHash             = {}
    @rootTrees          = nil               # the MiqMountManager objects using this MiqVolumeManager object

    @diskFileNames = vmCfg.getDiskFileHash

    `vgdisplay -c 2> /dev/null`.each { |vgl| vg = getVg(vgl); @vgHash[vg.vgName] = vg }
    `lvdisplay -c 2> /dev/null`.each { |lvl| lv = getLv(lvl); @lvHash[lv.lvPath] = lv }

    vgNames     = @vgHash.keys
    lvNames     = @lvHash.keys
    hiddenDevNames  = `pvdisplay -c 2> /dev/null`.split("\n").collect! { |p| p.lstrip.split(":", 2)[0] }

    if $log.debug?
      $log.debug "\nVolume Groups: (#{vgNames.class}: #{vgNames.length})"
      vgNames.each { |dn| $log.debug "\t#{dn}" }
      $log.debug "\nLogical Volumes: (#{lvNames.class}: #{lvNames.length})"
      lvNames.each { |dn| $log.debug "\t#{dn}" }
      $log.debug "\nHidden devs: (#{hiddenDevNames.class}: #{hiddenDevNames.length})"
    end

    physVolumes = openPhysicalVolumes(@diskFileNames)

    $log.debug "\nMiqNativeVolumeManager: physVolumes:" if $log.debug?
    physVolumes.each do |pv|
      if $log.debug?
        $log.debug "\t#{pv.devFile} => #{pv.dInfo.hardwareId} (SIG: #{pv.dInfo.diskSig})"
        $log.debug "\t\tPartition: #{pv.partNum}, Type: #{pv.partType}"
      end
      if hiddenDevNames.include?(pv.devFile)
        $log.debug "\t\t\tHIDDEN VOLUME" if $log.debug?
        hiddenVolumes << pv
      else
        @physicalVolumes << pv
      end
      @allPhysicalVolumes << pv
    end

    vgNames.each { |vgn| `vgchange -a y #{vgn}` }

    @logicalVolumes = openLogicalVolumes(lvNames)
    @visibleVolumes = @logicalVolumes + @physicalVolumes
  end

  def closeAll
    @wholeDisks.each(&:close)
    @logicalVolumes     = []
    @physicalVolumes    = []
    @hiddenVolumes      = []
    @wholeDisks         = []
    @vgHash             = nil
    @ost.miqVim.closeVdlConnection(@vdlConnection) if @vdlConnection
    @volMgrPS.postMount
  end

  def openLogicalVolumes(lvnames)
    lvList = []
    lvnames.each do |lvn|
      #
      # get MiqDisk object for each LV and add to lvList.
      #
      dInfo = OpenStruct.new
      dInfo.localDev = lvn
      dInfo.lvObj = @lvHash[lvn]
      dInfo.hardwareId = ""
      lvList << MiqDisk.getDisk(dInfo)
    end
    lvList
  end # def openLogicalVolumes

  def openPhysicalVolumes(diskFiles)
    pVolumes = []

    $log.debug "openPhysicalVolumes: no disk files supplied." unless diskFiles

    #
    # Build a list of the VM's physical volumes.
    #
    diskFiles.each do |dtag, df|
      $log.debug "openPhysicalVolumes: processing disk file (#{dtag}): #{df}"
      dInfo = OpenStruct.new
      dInfo.localDev = df
      dInfo.hardwareId = dtag

      begin
        d = MiqDisk.getDisk(dInfo)
        # I am not sure if getting a nil handle back should throw an error or not.
        # For now I am just skipping to the next disk.  (GMM)
        next if d.nil?
      rescue => err
        $log.error "Couldn't open disk file: #{df}"
        $log.error err.to_s
        $log.debug err.backtrace.join("\n")
        @diskInitErrors[df] = err.to_s
        next
      end

      @wholeDisks << d
      p = d.getPartitions
      if p.empty?
        #
        # If the disk has no partitions, the whole disk can be a single volume.
        #
        pVolumes << d
      else
        #
        # If the disk is partitioned, the partitions are physical volumes,
        # but not the whild disk.
        #
        pVolumes.concat(p)
      end
    end

    pVolumes
  end # def openPhysicalVolumes

  def getVg(vgl)
    vga = vgl.lstrip.split(":")
    (VolumeGroup.new(vga[16], vga[0]))
  end

  def getLv(lvl)
    lva = lvl.lstrip.split(":")
    lvPath = lva[0]
    vgName = lva[1]
    lvId   = `lvdisplay -v #{lvPath} 2> /dev/null | grep "LV UUID"`.split(" ").last
    lv  = LogicalVolume.new(lvId, File.basename(lvPath))

    vg = @vgHash[vgName]
    lv.vgObj  = vg
    lv.lvPath = lvPath
    vg.logicalVolumes[lv.lvName] = lv
  end
end # class MiqNativeVolumeManager