<commit_before>module ManageIQ::Providers::Openstack::ManagerMixin
  extend ActiveSupport::Concern

  alias_attribute :keystone_v3_domain_id, :uid_ems
  #
  # OpenStack interactions
  #
  module ClassMethods
    def raw_connect(username, password, auth_url, service = "Compute")
      require 'openstack/openstack_handle'
      OpenstackHandle::Handle.raw_connect(username, password, auth_url, service)
    end

    def auth_url(address, port = nil)
      require 'openstack/openstack_handle'
      OpenstackHandle::Handle.auth_url(address, port)
    end
  end

  def auth_url
    self.class.auth_url(address, port)
  end

  def browser_url
    "http://#{address}/dashboard"
  end

  def openstack_handle(options = {})
    require 'openstack/openstack_handle'
    @openstack_handle ||= begin
      raise MiqException::MiqInvalidCredentialsError, "No credentials defined" if self.missing_credentials?(options[:auth_type])

      username = options[:user] || authentication_userid(options[:auth_type])
      password = options[:pass] || authentication_password(options[:auth_type])

      vmdb_config = VMDB::Config.new("vmdb").config
      extra_options = {
        :ssl_ca_file    => vmdb_config.fetch_path(:ssl, :ssl_ca_file),
        :ssl_ca_path    => vmdb_config.fetch_path(:ssl, :ssl_ca_path),
        :ssl_cert_store => OpenSSL::X509::Store.new
      }
      extra_options[:domain_id] = keystone_v3_domain_id

      osh = OpenstackHandle::Handle.new(username, password, address, port, api_version, security_protocol, extra_options)
      osh.connection_options = {:instrumentor => $fog_log}
      osh
    end
  end

  def reset_openstack_handle
    @openstack_handle = nil
  end

  def connect(options = {})
    openstack_handle(options).connect(options)
  end

  def connect_volume
    connect(:service => "Volume")
  end

  def connect_identity
    connect(:service => "Identity")
  end

  def event_monitor_options
    @event_monitor_options ||= begin
      opts = {:ems => self}

      ceilometer = connection_configuration_by_role("ceilometer")

      if ceilometer.try(:endpoint) && !ceilometer.try(:endpoint).try(:marked_for_destruction?)
        opts[:events_monitor] = :ceilometer
      elsif (amqp = connection_configuration_by_role("amqp"))
        opts[:events_monitor] = :amqp
        if (endpoint = amqp.try(:endpoint))
          opts[:hostname]          = endpoint.hostname
          opts[:port]              = endpoint.port
          opts[:security_protocol] = endpoint.security_protocol
        end

        if (authentication = amqp.try(:authentication))
          opts[:username] = authentication.userid
          opts[:password] = <PASSWORD>
        end
      end
      opts
    end
  end

  def event_monitor_available?
    require 'openstack/openstack_event_monitor'
    OpenstackEventMonitor.available?(event_monitor_options)
  rescue => e
    _log.error("Exeption trying to find openstack event monitor for #{name}(#{hostname}). #{e.message}")
    false
  end

  def translate_exception(err)
    case err
    when Excon::Errors::Unauthorized
      MiqException::MiqInvalidCredentialsError.new "Login failed due to a bad username or password."
    when Excon::Errors::Timeout
      MiqException::MiqUnreachableError.new "Login attempt timed out"
    when Excon::Errors::SocketError
      MiqException::MiqHostError.new "Socket error: #{err.message}"
    when MiqException::MiqInvalidCredentialsError
      err
    else
      MiqException::MiqEVMLoginError.new "Unexpected response returned from system: #{err.message}"
    end
  end
<commit_msg>Restart OS event monitor on any endpoints and credentials change<commit_after>module ManageIQ::Providers::Openstack::ManagerMixin
  extend ActiveSupport::Concern

  included do
    after_save :stop_event_monitor_queue_on_change
    before_destroy :stop_event_monitor
  end

  alias_attribute :keystone_v3_domain_id, :uid_ems
  #
  # OpenStack interactions
  #
  module ClassMethods
    def raw_connect(username, password, auth_url, service = "Compute")
      require 'openstack/openstack_handle'
      OpenstackHandle::Handle.raw_connect(username, password, auth_url, service)
    end

    def auth_url(address, port = nil)
      require 'openstack/openstack_handle'
      OpenstackHandle::Handle.auth_url(address, port)
    end
  end

  def auth_url
    self.class.auth_url(address, port)
  end

  def browser_url
    "http://#{address}/dashboard"
  end

  def openstack_handle(options = {})
    require 'openstack/openstack_handle'
    @openstack_handle ||= begin
      raise MiqException::MiqInvalidCredentialsError, "No credentials defined" if self.missing_credentials?(options[:auth_type])

      username = options[:user] || authentication_userid(options[:auth_type])
      password = options[:pass] || authentication_password(options[:auth_type])

      vmdb_config = VMDB::Config.new("vmdb").config
      extra_options = {
        :ssl_ca_file    => vmdb_config.fetch_path(:ssl, :ssl_ca_file),
        :ssl_ca_path    => vmdb_config.fetch_path(:ssl, :ssl_ca_path),
        :ssl_cert_store => OpenSSL::X509::Store.new
      }
      extra_options[:domain_id] = keystone_v3_domain_id

      osh = OpenstackHandle::Handle.new(username, password, address, port, api_version, security_protocol, extra_options)
      osh.connection_options = {:instrumentor => $fog_log}
      osh
    end
  end

  def reset_openstack_handle
    @openstack_handle = nil
  end

  def connect(options = {})
    openstack_handle(options).connect(options)
  end

  def connect_volume
    connect(:service => "Volume")
  end

  def connect_identity
    connect(:service => "Identity")
  end

  def event_monitor_options
    @event_monitor_options ||= begin
      opts = {:ems => self}

      ceilometer = connection_configuration_by_role("ceilometer")

      if ceilometer.try(:endpoint) && !ceilometer.try(:endpoint).try(:marked_for_destruction?)
        opts[:events_monitor] = :ceilometer
      elsif (amqp = connection_configuration_by_role("amqp"))
        opts[:events_monitor] = :amqp
        if (endpoint = amqp.try(:endpoint))
          opts[:hostname]          = endpoint.hostname
          opts[:port]              = endpoint.port
          opts[:security_protocol] = endpoint.security_protocol
        end

        if (authentication = amqp.try(:authentication))
          opts[:username] = authentication.userid
          opts[:password] = <PASSWORD>
        end
      end
      opts
    end
  end

  def event_monitor_available?
    require 'openstack/openstack_event_monitor'
    OpenstackEventMonitor.available?(event_monitor_options)
  rescue => e
    _log.error("Exeption trying to find openstack event monitor for #{name}(#{hostname}). #{e.message}")
    false
  end

  def stop_event_monitor_queue_on_change
    if authentications.detect{ |x| x.previous_changes.present? } || endpoints.detect{ |x| x.previous_changes.present? }
      _log.info("EMS: [#{name}], Credentials or endpoints have changed, stopping Event Monitor. It will be restarted by the WorkerMonitor.")
      stop_event_monitor_queue
    end
  end

  def stop_event_monitor_queue_on_credential_change
    # TODO(lsmola) this check should not be needed. Right now we are saving each individual authentication and
    # it is breaking the check for changes. We should have it all saved by autosave when saving EMS, so the code
    # for authentications needs to be rewritten.
    stop_event_monitor_queue_on_change
  end

  def translate_exception(err)
    case err
    when Excon::Errors::Unauthorized
      MiqException::MiqInvalidCredentialsError.new "Login failed due to a bad username or password."
    when Excon::Errors::Timeout
      MiqException::MiqUnreachableError.new "Login attempt timed out"
    when Excon::Errors::SocketError
      MiqException::MiqHostError.new "Socket error: #{err.message}"
    when MiqException::MiqInvalidCredentialsError
      err
    else
      MiqException::MiqEVMLoginError.new "Unexpected response returned from system: #{err.message}"
    end
  end

{'fraction_non_alphanumeric': 0.09565325694357953, 'fraction_numerical': 0.0012454851164528584, 'mean_word_length': 3.6849474912485416, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3952204', 'n_tokens_mistral': 2401, 'n_tokens_neox': 2351, 'n_words': 512}