<commit_before>module ManageIQ::Providers
  module Openstack
    module RefreshParserCommon
      module Networks
        def security_groups
          @security_groups ||= @network_service.handled_list(:security_groups)
        end

        def networks
          @networks ||= @network_service.handled_list(:networks)
        end

        def network_ports
          @network_ports ||= @network_service.handled_list(:ports)
        end

        def network_routers
          @network_routers ||= @network_service.handled_list(:routers)
        end

        def floating_ips_neutron
          @network_service.handled_list(:floating_ips)
        end

        # maintained for legacy nova network support
        def floating_ips_nova
          @connection.handled_list(:addresses)
        end

        def get_networks
          return unless @network_service.name == :neutron

          process_collection(networks, :cloud_networks) { |n| parse_network(n) }
          get_subnets
        end

        def get_network_routers
          return unless @network_service.name == :neutron

          process_collection(network_routers, :network_routers) { |n| parse_network_router(n) }
        end

        def get_network_ports
          return unless @network_service.name == :neutron

          process_collection(network_ports, :network_ports) { |n| parse_network_port(n) }
        end

        def get_subnets
          return unless @network_service.name == :neutron

          networks.each do |n|
            new_net = @data_index.fetch_path(:cloud_networks, n.id)
            new_net[:cloud_subnets] = n.subnets.collect { |s| parse_subnet(s) }

            # Lets store also subnets into indexed data, so we can reference them elsewhere
            new_net[:cloud_subnets].each { |x| @data_index.store_path(:cloud_subnets, x[:ems_ref], x) }
          end
        end

        def get_floating_ips
          ips = send("floating_ips_#{@network_service.name}")
          process_collection(ips, :floating_ips) { |ip| parse_floating_ip(ip) }
        end

        def get_security_groups
          process_collection(security_groups, :security_groups) { |sg| parse_security_group(sg) }
          get_firewall_rules
        end

        def get_firewall_rules
          security_groups.each do |sg|
            new_sg = @data_index.fetch_path(:security_groups, sg.id)
            new_sg[:firewall_rules] = sg.security_group_rules.collect { |r| parse_firewall_rule(r) }
          end
        end

        def parse_security_group(sg)
          uid, security_group = super
          security_group[:cloud_tenant]        = @data_index.fetch_path(:cloud_tenants, sg.tenant_id)
          security_group[:orchestration_stack] = @data_index.fetch_path(:orchestration_stacks, @resource_to_stack[uid])
          return uid, security_group
        end

        # TODO: Should ICMP protocol values have their own 2 columns, or
        #   should they override port and end_port like the Amazon API.
        def parse_firewall_rule(rule)
          send("parse_firewall_rule_#{@network_service.name}", rule)
        end

        def parse_network(network)
          uid     = network.id
          status  = (network.status.to_s.downcase == "active") ? "active" : "inactive"

          network_type_suffix = network.router_external ? "::Public" : "::Private"

          new_result = {
            :type                      => self.class.cloud_network_type + network_type_suffix,
            :name                      => network.name,
            :ems_ref                   => uid,
            :shared                    => network.shared,
            :status                    => status,
            :enabled                   => network.admin_state_up,
            :external_facing           => network.router_external,
            :cloud_tenant              => @data_index.fetch_path(:cloud_tenants, network.tenant_id),
            :orchestration_stack       => @data_index.fetch_path(:orchestration_stacks, @resource_to_stack[uid]),
            :provider_physical_network => network.provider_physical_network,
            :provider_network_type     => network.provider_network_type,
            :provider_segmentation_id  => network.provider_segmentation_id,
            :vlan_transparent          => network.attributes["vlan_transparent"],
            # TODO(lsmola) expose attributes in FOG
            :maximum_transmission_unit => network.attributes["mtu"],
            :port_security_enabled     => network.attributes["port_security_enabled"],
          }
          return uid, new_result
        end

        def find_device_object(network_port)
          case network_port.device_owner
          when /^compute\:.*?$/
            # Owner is in format compute:<availability_zone> or compute:None
            find_device_connected_to_network_port(network_port.device_id)
          when "network:router_gateway"
            # TODO(lsmola) we need to represent gateway as object
          when "network:dhcp"
            # TODO(lsmola) we need to represent dhcp as object
          when "network:floatingip"
            @data_index.fetch_path(:floating_ips, network_port.device_id)
          when "network:router_interface"
            @data_index.fetch_path(:network_routers, network_port.device_id)
          end
        end

        def parse_network_port(network_port)
          uid             = network_port.id
          # There can be multiple fixed_ips on the port, but only under one subnet
          subnet_id       = network_port.fixed_ips.try(:first).try(:[], "subnet_id")
          device          = find_device_object(network_port)
          security_groups = network_port.security_groups.map { |x| @data_index.fetch_path(:security_groups, x) }

          new_result = {
            :type                              => self.class.network_port_type,
            :name                              => network_port.name,
            :ems_ref                           => uid,
            :status                            => network_port.status,
            :admin_state_up                    => network_port.admin_state_up,
            :cloud_network                     => @data_index.fetch_path(:cloud_networks, network_port.network_id),
            :cloud_subnet                      => @data_index.fetch_path(:cloud_subnets, subnet_id),
            :mac_address                       => network_port.attributes[:mac_address],
            :device_owner                      => network_port.device_owner,
            :device_ref                        => network_port.device_id,
            :device                            => device,
            :cloud_tenant                      => @data_index.fetch_path(:cloud_tenants, network_port.tenant_id),
            # TODO(lsmola) expose missing atttributes in FOG<commit_msg>Check for presence of security groups<commit_after>module ManageIQ::Providers
  module Openstack
    module RefreshParserCommon
      module Networks
        def security_groups
          @security_groups ||= @network_service.handled_list(:security_groups)
        end

        def networks
          @networks ||= @network_service.handled_list(:networks)
        end

        def network_ports
          @network_ports ||= @network_service.handled_list(:ports)
        end

        def network_routers
          @network_routers ||= @network_service.handled_list(:routers)
        end

        def floating_ips_neutron
          @network_service.handled_list(:floating_ips)
        end

        # maintained for legacy nova network support
        def floating_ips_nova
          @connection.handled_list(:addresses)
        end

        def get_networks
          return unless @network_service.name == :neutron

          process_collection(networks, :cloud_networks) { |n| parse_network(n) }
          get_subnets
        end

        def get_network_routers
          return unless @network_service.name == :neutron

          process_collection(network_routers, :network_routers) { |n| parse_network_router(n) }
        end

        def get_network_ports
          return unless @network_service.name == :neutron

          process_collection(network_ports, :network_ports) { |n| parse_network_port(n) }
        end

        def get_subnets
          return unless @network_service.name == :neutron

          networks.each do |n|
            new_net = @data_index.fetch_path(:cloud_networks, n.id)
            new_net[:cloud_subnets] = n.subnets.collect { |s| parse_subnet(s) }

            # Lets store also subnets into indexed data, so we can reference them elsewhere
            new_net[:cloud_subnets].each { |x| @data_index.store_path(:cloud_subnets, x[:ems_ref], x) }
          end
        end

        def get_floating_ips
          ips = send("floating_ips_#{@network_service.name}")
          process_collection(ips, :floating_ips) { |ip| parse_floating_ip(ip) }
        end

        def get_security_groups
          process_collection(security_groups, :security_groups) { |sg| parse_security_group(sg) }
          get_firewall_rules
        end

        def get_firewall_rules
          security_groups.each do |sg|
            new_sg = @data_index.fetch_path(:security_groups, sg.id)
            new_sg[:firewall_rules] = sg.security_group_rules.collect { |r| parse_firewall_rule(r) }
          end
        end

        def parse_security_group(sg)
          uid, security_group = super
          security_group[:cloud_tenant]        = @data_index.fetch_path(:cloud_tenants, sg.tenant_id)
          security_group[:orchestration_stack] = @data_index.fetch_path(:orchestration_stacks, @resource_to_stack[uid])
          return uid, security_group
        end

        # TODO: Should ICMP protocol values have their own 2 columns, or
        #   should they override port and end_port like the Amazon API.
        def parse_firewall_rule(rule)
          send("parse_firewall_rule_#{@network_service.name}", rule)
        end

        def parse_network(network)
          uid     = network.id
          status  = (network.status.to_s.downcase == "active") ? "active" : "inactive"

          network_type_suffix = network.router_external ? "::Public" : "::Private"

          new_result = {
            :type                      => self.class.cloud_network_type + network_type_suffix,
            :name                      => network.name,
            :ems_ref                   => uid,
            :shared                    => network.shared,
            :status                    => status,
            :enabled                   => network.admin_state_up,
            :external_facing           => network.router_external,
            :cloud_tenant              => @data_index.fetch_path(:cloud_tenants, network.tenant_id),
            :orchestration_stack       => @data_index.fetch_path(:orchestration_stacks, @resource_to_stack[uid]),
            :provider_physical_network => network.provider_physical_network,
            :provider_network_type     => network.provider_network_type,
            :provider_segmentation_id  => network.provider_segmentation_id,
            :vlan_transparent          => network.attributes["vlan_transparent"],
            # TODO(lsmola) expose attributes in FOG
            :maximum_transmission_unit => network.attributes["mtu"],
            :port_security_enabled     => network.attributes["port_security_enabled"],
          }
          return uid, new_result
        end

        def find_device_object(network_port)
          case network_port.device_owner
          when /^compute\:.*?$/
            # Owner is in format compute:<availability_zone> or compute:None
            find_device_connected_to_network_port(network_port.device_id)
          when "network:router_gateway"
            # TODO(lsmola) we need to represent gateway as object
          when "network:dhcp"
            # TODO(lsmola) we need to represent dhcp as object
          when "network:floatingip"
            @data_index.fetch_path(:floating_ips, network_port.device_id)
          when "network:router_interface"
            @data_index.fetch_path(:network_routers, network_port.device_id)
          end
        end

        def parse_network_port(network_port)
          uid             = network_port.id
          # There can be multiple fixed_ips on the port, but only under one subnet
          subnet_id       = network_port.fixed_ips.try(:first).try(:[], "subnet_id")
          device          = find_device_object(network_port)
          security_groups = network_port.security_groups.blank? ? [] :network_port.security_groups.map do |x|
            @data_index.fetch_path(:security_groups, x)
          end

          new_result = {
            :type                              => self.class.network_port_type,
            :name                              => network_port.name,
            :ems_ref                           => uid,
            :status                            => network_port.status,
            :admin_state_up                    => network_port.admin_state_up,
            :cloud_network                     => @data_index.fetch_path(:cloud_networks, network_port.network_id),
            :cloud_subnet                      => @data_index.fetch_path(:cloud_subnets, subnet_id),
            :mac_address                       => network_port.attributes[:mac_address],
            :device_owner                      => network_port.device_owner,
            :device_ref                        => network_port.device_id,
            :device                            => device,
            :cloud_tenant                      => @data_index.fetch_path(:cloud_tenants, network_port.tenant_id),
            # TODO(lsmola) expose missing atttributes in FOG
{'fraction_non_alphanumeric': 0.08131676477000219, 'fraction_numerical': 0.0001453382748346777, 'mean_word_length': 1.9794327776575016, 'pattern_counts': {'":': 4, '<': 5, '<?xml version=': 0, '>': 59, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1567194', 'n_tokens_mistral': 3811, 'n_tokens_neox': 3698, 'n_words': 697}