Created
February 8, 2024 16:32
-
-
Save agrare/22b1bef6c6e1324fdc8e3bd4e40580b5 to your computer and use it in GitHub Desktop.
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
class ManageIQ::Providers::Azure::Inventory::Parser::NetworkManager < ManageIQ::Providers::Azure::Inventory::Parser | |
def parse | |
log_header = "Collecting data for EMS : [#{collector.manager.name}] id: [#{collector.manager.id}]" | |
@data_index = {} | |
_log.info("#{log_header}...") | |
security_groups | |
cloud_networks | |
network_ports | |
load_balancers | |
floating_ips | |
network_routers | |
_log.info("#{log_header}...Complete") | |
end | |
private | |
def security_groups | |
collector.security_groups.each do |security_group| | |
uid = security_group.id | |
description = [ | |
security_group.resource_group, | |
security_group.location | |
].join('-') | |
persister_security_group = persister.security_groups.build( | |
:ems_ref => uid, | |
:name => security_group.name, | |
:description => description, | |
) | |
firewall_rules(persister_security_group, security_group) | |
end | |
end | |
def firewall_rules(persister_security_group, security_group) | |
security_group.properties.security_rules.each do |rule| | |
persister.firewall_rules.build( | |
:resource => persister_security_group, | |
:name => rule.name, | |
:host_protocol => rule.properties.protocol.upcase, | |
:port => calculate_start_port(rule), | |
:end_port => calculate_end_port(rule), | |
:direction => rule.properties.direction, | |
:source_ip_range => calculate_source_ip_range(rule), | |
:source_security_group => persister.security_groups.lazy_find(security_group.id), | |
) | |
end | |
end | |
def cloud_networks | |
# TODO(lsmola) solve with secondary indexes for version > g | |
if persister.stack_resources_secondary_index.blank? | |
manager = persister.manager.respond_to?(:parent_manager) ? persister.manager.parent_manager : persister.manager | |
manager.orchestration_stacks_resources.find_each do |resource| | |
persister.stack_resources_secondary_index[resource[:ems_ref].downcase] ||= | |
InventoryRefresh::ApplicationRecordReference.new(OrchestrationStack, resource.stack_id) | |
end | |
end | |
collector.cloud_networks.each do |cloud_network| | |
uid = cloud_network.id | |
persister_cloud_networks = persister.cloud_networks.build( | |
:ems_ref => uid, | |
:name => cloud_network.name, | |
:cidr => cloud_network.properties.address_space.address_prefixes.join(", "), | |
:enabled => true, | |
:orchestration_stack => persister.stack_resources_secondary_index[uid.downcase], | |
) | |
cloud_subnets(persister_cloud_networks, cloud_network) | |
end | |
end | |
def cloud_subnets(persister_cloud_networks, cloud_network) | |
cloud_network.properties.subnets.each do |subnet| | |
uid = subnet.id | |
_log.info("TEST Subnet: #{subnet.name} properties: [#{subnet.instance_variable_get(:@hash)}]") | |
persister.cloud_subnets.build( | |
:ems_ref => uid, | |
:name => subnet.name, | |
:cidr => subnet.properties.try(:address_prefix), | |
:cloud_network => persister_cloud_networks, | |
:availability_zone => persister.availability_zones.lazy_find('default'), | |
:network_router => persister.network_routers.lazy_find(subnet.properties.try(:route_table).try(:id)) | |
) | |
end | |
end | |
def network_routers | |
collector.network_routers.each do |router| | |
persister.network_routers.build( | |
:ems_ref => router.id, | |
:name => router.name, | |
:type => ManageIQ::Providers::Azure::NetworkManager::NetworkRouter.name, | |
:status => router.properties.try(:subnets) ? 'active' : 'inactive', | |
:extra_attributes => { :routes => get_route_attributes(router) } | |
) | |
end | |
end | |
def get_route_attributes(router) | |
router.properties.routes.map do |route| | |
{ | |
'Name' => route.name, | |
'Resource Group' => route.resource_group, | |
'CIDR' => route.properties.address_prefix | |
} | |
end | |
end | |
def network_ports | |
collector.network_ports.each do |network_port| | |
uid = network_port.id | |
vm_id = resource_id_for_instance_id(network_port.properties.try(:virtual_machine).try(:id)) | |
security_groups = [ | |
persister.security_groups.lazy_find(network_port.properties.try(:network_security_group).try(:id)) | |
].compact | |
persister_network_port = persister.network_ports.build( | |
:name => network_port.name, | |
:ems_ref => uid, | |
:status => network_port.properties.try(:provisioning_state), | |
:mac_address => network_port.properties.try(:mac_address), | |
:device_ref => network_port.properties.try(:virtual_machine).try(:id), | |
:device => persister.vms.lazy_find(vm_id), | |
:security_groups => security_groups, | |
:source => "refresh", | |
) | |
network_port.properties.ip_configurations.map do |x| | |
persister.cloud_subnet_network_ports.build( | |
:address => x.properties.try(:private_ip_address), | |
:cloud_subnet => persister.cloud_subnets.lazy_find(x.properties.try(:subnet).try(:id)), | |
:network_port => persister_network_port | |
) | |
persister.cloud_subnet_network_ports_secondary_index[uid] ||= x.properties.try(:private_ip_address) | |
end | |
end | |
end | |
def load_balancers | |
collector.load_balancers.each do |lb| | |
name = lb.name | |
uid = lb.id | |
persister_load_balancer = persister.load_balancers.build( | |
:ems_ref => uid, | |
:name => name, | |
) | |
load_balancer_listeners(persister_load_balancer, lb) | |
load_balancer_network_port(persister_load_balancer, lb) | |
end | |
collector.load_balancers.each do |lb| | |
# Depends on order, needs listeners computed first | |
load_balancer_health_checks(persister.load_balancers.lazy_find(lb.id), lb) | |
end | |
end | |
def load_balancer_pools(lb, pool_id) | |
lb.properties["backendAddressPools"].each do |pool| | |
uid = pool.id | |
next unless pool_id == uid # TODO(lsmola) find more effective way | |
persister_load_balancer_pool = persister.load_balancer_pools.build( | |
:ems_ref => uid, | |
:name => pool.name, | |
) | |
load_balancer_pool_members(persister_load_balancer_pool, pool) | |
end | |
end | |
def load_balancer_pool_members(persister_load_balancer_pool, pool) | |
pool["properties"]["backendIPConfigurations"].to_a.each do |ipconfig| | |
uid = ipconfig.id | |
nic_id = uid.split("/")[0..-3].join("/") # Convert IpConfiguration id to networkInterfaces id | |
persister_load_balancer_pool_member = persister.load_balancer_pool_members.build( | |
:ems_ref => uid, | |
:vm => persister.network_ports.lazy_find(nic_id, :key => :device) | |
) | |
persister.load_balancer_pool_member_pools.build( | |
:load_balancer_pool => persister_load_balancer_pool, | |
:load_balancer_pool_member => persister_load_balancer_pool_member | |
) | |
end | |
end | |
def load_balancer_listeners(persister_load_balancer, lb) | |
lb.properties["loadBalancingRules"].each do |listener| | |
uid = listener["id"] | |
pool_id = listener.properties["backendAddressPool"]["id"] | |
backend_port = listener.properties["backendPort"].to_i | |
frontend_port = listener.properties["frontendPort"].to_i | |
persister_load_balancer_listener = persister.load_balancer_listeners.build( | |
:ems_ref => uid, | |
:load_balancer_protocol => listener.properties["protocol"], | |
:load_balancer_port_range => (backend_port..backend_port), | |
:instance_protocol => listener.properties["protocol"], | |
:instance_port_range => (frontend_port..frontend_port), | |
:load_balancer => persister_load_balancer, | |
) | |
persister.load_balancer_listener_pools.build( | |
:load_balancer_listener => persister_load_balancer_listener, | |
:load_balancer_pool => persister.load_balancer_pools.lazy_find(pool_id) | |
) | |
load_balancer_pools(lb, pool_id) | |
end | |
end | |
def load_balancer_network_port(persister_load_balancer, lb) | |
uid = "#{lb.id}/nic1" | |
persister.network_ports.build( | |
:device_ref => lb.id, | |
:device => persister_load_balancer, | |
:ems_ref => uid, | |
:name => File.basename(lb.id) + '/nic1', | |
:status => "Succeeded", | |
:source => "refresh", | |
) | |
end | |
def load_balancer_health_checks(persister_load_balancer, lb) | |
# TODO(lsmola) think about adding members through listeners on model side, since copying deep nested relations of | |
# members is not efficient | |
# Index load_balancer_pool_member_pools by load_balancer_pool, so we can fetch members of each pool | |
by_load_balancer_pool_member_pools = persister.load_balancer_pool_member_pools.data.each_with_object({}) do |x, obj| | |
(obj[x[:load_balancer_pool].try(:[], :ems_ref)] ||= []) << x[:load_balancer_pool_member] | |
end | |
# Index load_balancer_pool by load_balancer_listener, so we can pools of each listener | |
by_load_balancer_listeners = persister.load_balancer_listener_pools.data.each_with_object({}) do |x, obj| | |
obj[x[:load_balancer_listener].try(:[], :ems_ref)] = x[:load_balancer_pool].try(:[], :ems_ref) | |
end | |
lb.properties["probes"].each do |health_check| | |
uid = health_check.id | |
load_balancing_rules = health_check.properties["loadBalancingRules"] | |
# TODO(lsmola) Does Azure support multiple listeners per health check? If yes, the modeling of members through | |
# listeners would need migration | |
health_check_listener = persister.load_balancer_listeners.lazy_find(load_balancing_rules.first.id) if load_balancing_rules | |
persister_load_balancer_health_check = persister.load_balancer_health_checks.build( | |
:ems_ref => uid, | |
:protocol => health_check.properties["protocol"], | |
:port => health_check.properties["port"], | |
:interval => health_check.properties["intervalInSeconds"], | |
:url_path => health_check.properties["requestPath"], | |
:load_balancer => persister_load_balancer, | |
:load_balancer_listener => health_check_listener, | |
) | |
next if load_balancing_rules.blank? | |
# We will copy members of our listeners into health check members | |
health_check_members = health_check | |
.properties["loadBalancingRules"] | |
.map { |x| by_load_balancer_listeners[x.id] } | |
.map { |x| by_load_balancer_pool_member_pools[x] } | |
.flatten | |
health_check_members.compact.each do |health_check_member| | |
persister.load_balancer_health_check_members.build( | |
:load_balancer_health_check => persister_load_balancer_health_check, | |
:load_balancer_pool_member => health_check_member, | |
) | |
end | |
end | |
end | |
def floating_ips | |
collector.floating_ips.each do |ip| | |
uid = ip.id | |
# TODO(lsmola) get rid of all the find method that are ineffective, a lazy_find multi should solve it | |
network_port_id = floating_ip_network_port_id(ip) | |
network_port = persister.network_ports.find(network_port_id) | |
if network_port | |
vm = network_port.try(:[], :device) | |
elsif persister.load_balancers.find(network_port_id) | |
network_port = persister.network_ports.lazy_find("#{network_port_id}/nic1") | |
end | |
persister.floating_ips.build( | |
:ems_ref => uid, | |
:status => ip.properties.try(:provisioning_state), | |
:address => ip.properties.try(:ip_address) || ip.name, | |
:network_port => network_port, | |
:fixed_ip_address => persister.cloud_subnet_network_ports_secondary_index[network_port_id], | |
:vm => vm | |
) | |
end | |
end | |
def calculate_source_ip_range(rule) | |
if rule.properties.respond_to?(:source_address_prefix) | |
rule.properties.source_address_prefix | |
elsif rule.properties.respond_to?(:source_address_prefixes) | |
rule.properties.source_address_prefixes.join(',') | |
end | |
end | |
def calculate_start_port(rule) | |
if rule.properties.respond_to?(:destination_port_range) | |
rule.properties.destination_port_range.split('-').first.to_i | |
elsif rule.properties.respond_to?(:destination_port_ranges) | |
rule.properties.destination_port_ranges.flat_map { |e| e.split('-') }.map(&:to_i).min | |
end | |
end | |
def calculate_end_port(rule) | |
if rule.properties.respond_to?(:destination_port_range) | |
rule.properties.destination_port_range.split('-').last.to_i | |
elsif rule.properties.respond_to?(:destination_port_ranges) | |
rule.properties.destination_port_ranges.flat_map { |e| e.split('-') }.map(&:to_i).max | |
end | |
end | |
def floating_ip_network_port_id(ip) | |
# TODO(lsmola) NetworkManager, we need to model ems_ref in model CloudSubnetNetworkPort and relate floating | |
# ip to that model | |
# For now cutting last 2 / from the id, to get just the id of the network_port. ID looks like: | |
# /subscriptions/{guid}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/networkInterfaces/vm1nic1/ipConfigurations/ip1 | |
# where id of the network port is | |
# /subscriptions/{guid}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/networkInterfaces/vm1nic1 | |
cloud_subnet_network_port_id = ip.properties.try(:ip_configuration).try(:id) | |
cloud_subnet_network_port_id.split("/")[0..-3].join("/") if cloud_subnet_network_port_id | |
end | |
def resource_id_for_instance_id(id) | |
# TODO(lsmola) we really need to get rid of the building our own emf_ref, it makes crosslinking impossible, parsing | |
# the id string like this is suboptimal | |
return nil unless id | |
_, _, guid, _, resource_group, _, type, sub_type, name = id.split("/") | |
File.join(guid, resource_group.downcase, type.downcase, sub_type.downcase, name) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment