forked from ManageIQ/manageiq-providers-lenovo
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request ManageIQ#139 from douglasgabriel/rft_parse_structure
Refactoring the parse structure
- Loading branch information
Showing
7 changed files
with
395 additions
and
318 deletions.
There are no files selected for viewing
42 changes: 42 additions & 0 deletions
42
...s/manageiq/providers/lenovo/physical_infra_manager/parsers/components/component_parser.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
module ManageIQ::Providers::Lenovo | ||
module Parsers | ||
# | ||
# Superclass extended by all classes that parses LXCA components | ||
# to a MiQ format | ||
# | ||
class ComponentParser | ||
# | ||
# Returns a hash containing the structure described on dictionary | ||
# and with the values in the source. | ||
# | ||
# @param source - Object that will be parse to a hash | ||
# @param dictionary - Hash containing the instructions to translate the object into a Hash | ||
# | ||
# @see ParserDictionaryConstants | ||
# | ||
def self.parse(source, dictionary) | ||
result = {} | ||
dictionary&.each do |key, value| | ||
if value.kind_of?(String) | ||
next if value.empty? | ||
source_keys = value.split('.') # getting source keys navigation | ||
source_value = source | ||
source_keys.each do |source_key| | ||
begin | ||
attr_method = source_value.method(source_key) # getting method to get the attribute value | ||
source_value = attr_method.call | ||
rescue NameError | ||
# when the key doesn't correspond to a method | ||
source_value = source_value[source_key] | ||
end | ||
end | ||
result[key] = source_value | ||
elsif value.kind_of?(Hash) | ||
result[key] = parse(source, dictionary[key]) | ||
end | ||
end | ||
result | ||
end | ||
end | ||
end | ||
end |
21 changes: 21 additions & 0 deletions
21
...ageiq/providers/lenovo/physical_infra_manager/parsers/components/config_pattern_parser.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
require_relative 'component_parser' | ||
|
||
module ManageIQ::Providers::Lenovo | ||
module Parsers | ||
class ConfigPatternParser < ComponentParser | ||
class << self | ||
# | ||
# Parses the config pattern object into a Hash | ||
# | ||
# @param [XClarityClient::ConfigPattern] config_pattern - object containing config | ||
# pattern data | ||
# | ||
# @return [Hash] containing the config pattern informations | ||
# | ||
def parse_config_pattern(config_pattern) | ||
return config_pattern.id, parse(config_pattern, ParserDictionaryConstants::CONFIG_PATTERNS) | ||
end | ||
end | ||
end | ||
end | ||
end |
236 changes: 236 additions & 0 deletions
236
...geiq/providers/lenovo/physical_infra_manager/parsers/components/physical_server_parser.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,236 @@ | ||
require_relative 'component_parser' | ||
|
||
module ManageIQ::Providers::Lenovo | ||
module Parsers | ||
class PhysicalServerParser < ComponentParser | ||
class << self | ||
# | ||
# parse a node object to a hash with physical servers data | ||
# | ||
# @param [XClarityClient::Node] node - object containing physical server data | ||
# | ||
# @return [Hash] containing the physical server information | ||
# | ||
def parse_physical_server(node) | ||
result = parse(node, ParserDictionaryConstants::PHYSICAL_SERVER) | ||
|
||
result[:vendor] = "lenovo" | ||
result[:type] = ParserDictionaryConstants::MIQ_TYPES["physical_server"] | ||
result[:power_state] = ParserDictionaryConstants::POWER_STATE_MAP[node.powerStatus] | ||
result[:health_state] = ParserDictionaryConstants::HEALTH_STATE_MAP[node.cmmHealthState.nil? ? node.cmmHealthState : node.cmmHealthState.downcase] | ||
result[:host] = get_host_relationship(node.serialNumber) | ||
result[:location_led_state] = find_loc_led_state(node.leds) | ||
result[:computer_system][:hardware] = get_hardwares(node) | ||
|
||
return node.uuid, result | ||
end | ||
|
||
private | ||
|
||
# Assign a physicalserver and host if server already exists and | ||
# some host match with physical Server's serial number | ||
def get_host_relationship(serial_number) | ||
Host.find_by(:service_tag => serial_number) || | ||
Host.joins(:hardware).find_by('hardwares.serial_number' => serial_number) | ||
end | ||
|
||
# Find the identification led state | ||
def find_loc_led_state(leds) | ||
identification_led = leds.to_a.find { |led| ParserDictionaryConstants::PROPERTIES_MAP[:led_identify_name].include?(led["name"]) } | ||
identification_led.try(:[], "state") | ||
end | ||
|
||
def get_hardwares(node) | ||
{ | ||
:disk_capacity => get_disk_capacity(node), | ||
:memory_mb => get_memory_info(node), | ||
:cpu_total_cores => get_total_cores(node), | ||
:firmwares => get_firmwares(node), | ||
:guest_devices => get_guest_devices(node) | ||
} | ||
end | ||
|
||
def get_disk_capacity(node) | ||
total_disk_cap = 0 | ||
node.raidSettings&.each do |storage| | ||
storage['diskDrives']&.each do |disk| | ||
total_disk_cap += disk['capacity'] unless disk['capacity'].nil? | ||
end | ||
end | ||
total_disk_cap | ||
end | ||
|
||
def get_memory_info(node) | ||
total_memory_gigabytes = node.memoryModules&.reduce(0) { |total, mem| total + mem['capacity'] } | ||
total_memory_gigabytes * 1024 # convert to megabytes | ||
end | ||
|
||
def get_total_cores(node) | ||
node.processors&.reduce(0) { |total, pr| total + pr['cores'] } | ||
end | ||
|
||
def get_firmwares(node) | ||
node.firmware&.map { |firmware| parse_firmware(firmware) } | ||
end | ||
|
||
def get_guest_devices(node) | ||
guest_devices = get_addin_cards(node) | ||
guest_devices << parse_management_device(node) | ||
pci_devices = parse_pci_devices(node) | ||
guest_devices.push(*pci_devices) | ||
end | ||
|
||
def parse_firmware(firmware) | ||
{ | ||
:name => "#{firmware["role"]} #{firmware["name"]}-#{firmware["status"]}", | ||
:build => firmware["build"], | ||
:version => firmware["version"], | ||
:release_date => firmware["date"], | ||
} | ||
end | ||
|
||
def get_addin_cards(node) | ||
parsed_addin_cards = [] | ||
node.addinCards&.each { |node_addin_card| get_cards_info(node_addin_card, parsed_addin_cards) } | ||
parsed_addin_cards | ||
end | ||
|
||
# For each of the node's card, parse the card and then see | ||
# if it is already in the list of parsed cards. If it is, see if | ||
# all of its ports are already in the existing parsed card entry. | ||
# If it's not, then add the port to the existing card entry and | ||
# don't add the card again to the list of parsed cards. | ||
# This is needed because xclarity_client seems to represent each port | ||
# as a separate card. The code below ensures that each addin | ||
# card is represented by a single card with multiple ports. | ||
# | ||
# @param card [Hash] can be either a node's addinCard or a pciDevice | ||
# @param parsed_cards [Array] a list that will be modified to contain all parsed cards | ||
def get_cards_info(card, parsed_cards) | ||
return unless get_device_type(card) == "ethernet" | ||
|
||
add_card = true | ||
parsed_node_card = parse_card(card) | ||
|
||
parsed_cards.each do |addin_card| | ||
next unless parsed_node_card[:device_name] == addin_card[:device_name] || | ||
parsed_node_card[:location] == addin_card[:location] | ||
|
||
parsed_node_card[:child_devices].each do |parsed_port| | ||
card_found = false | ||
addin_card[:child_devices].each do |port| | ||
if parsed_port[:device_name] == port[:device_name] | ||
card_found = true | ||
end | ||
end | ||
unless card_found | ||
addin_card[:child_devices].push(parsed_port) | ||
add_card = false | ||
end | ||
end | ||
end | ||
|
||
if add_card | ||
parsed_cards.push(parsed_node_card) | ||
end | ||
end | ||
|
||
def get_device_type(card) | ||
device_type = "" | ||
|
||
unless card["name"].nil? | ||
card_name = card["name"].downcase | ||
if card_name.include?("nic") || card_name.include?("ethernet") | ||
device_type = "ethernet" | ||
end | ||
end | ||
device_type | ||
end | ||
|
||
def parse_pci_devices(node) | ||
parsed_pci_devices = [] | ||
node.pciDevices&.each { |pci_device| get_guest_device_ports(pci_device) } | ||
parsed_pci_devices | ||
end | ||
|
||
def parse_card(card) | ||
{ | ||
:device_name => card["productName"], | ||
:device_type => get_device_type(card), | ||
:firmwares => get_guest_device_firmware(card), | ||
:manufacturer => card["manufacturer"], | ||
:field_replaceable_unit => card["FRU"], | ||
:location => "Bay #{card['slotNumber']}", | ||
:child_devices => get_guest_device_ports(card) | ||
} | ||
end | ||
|
||
def parse_management_device(node) | ||
{ | ||
:device_type => "management", | ||
:network => parse_management_network(node), | ||
:address => node.macAddress | ||
} | ||
end | ||
|
||
def get_guest_device_firmware(card) | ||
device_fw = [] | ||
|
||
unless card.nil? | ||
firmware = card["firmware"] | ||
unless firmware.nil? | ||
device_fw = firmware.map do |fw| | ||
parse_firmware(fw) | ||
end | ||
end | ||
end | ||
|
||
device_fw | ||
end | ||
|
||
def get_guest_device_ports(card) | ||
device_ports = [] | ||
|
||
if card && card["portInfo"] | ||
port_info = card["portInfo"] | ||
physical_ports = port_info["physicalPorts"] | ||
physical_ports&.each do |physical_port| | ||
parsed_physical_port = parse_physical_port(physical_port) | ||
logical_ports = physical_port["logicalPorts"] | ||
parsed_logical_port = parse_logical_port(logical_ports[0]) | ||
device_ports.push(parsed_logical_port.merge(parsed_physical_port)) | ||
end | ||
end | ||
|
||
device_ports | ||
end | ||
|
||
def parse_physical_port(port) | ||
{ | ||
:device_type => "physical_port", | ||
:device_name => "Physical Port #{port['physicalPortIndex']}" | ||
} | ||
end | ||
|
||
def parse_management_network(node) | ||
{ | ||
:ipaddress => node.mgmtProcIPaddress, | ||
:ipv6address => node.ipv6Addresses.nil? ? node.ipv6Addresses : node.ipv6Addresses.join(", ") | ||
} | ||
end | ||
|
||
def parse_logical_port(port) | ||
{ | ||
:address => format_mac_address(port["addresses"]), | ||
:vlan_enabled => port["vnicMode"], | ||
:vlan_key => port["logicalPortIndex"], | ||
} | ||
end | ||
|
||
def format_mac_address(mac_address) | ||
mac_address.scan(/\w{2}/).join(":") | ||
end | ||
end | ||
end | ||
end | ||
end |
Oops, something went wrong.