<commit_before>$:.push("#{File.dirname(__FILE__)}/../../../lib/util/xml")
$:.push(File.expand_path(File.join(Rails.root, %w{.. lib util win32})))
$:.push("#{File.dirname(__FILE__)}/../../../lib/metadata/linux")

require 'ostruct'
require 'MiqSockUtil'
require 'xml_utils'
require 'cgi'               # Used for URL encoding/decoding
require 'LinuxUsers'
require 'LinuxUtils'

$:.push("#{File.dirname(__FILE__)}/../../../lib/metadata/ScanProfile")
require 'HostScanProfiles'

class Host < ActiveRecord::Base
  include NewWithTypeStiMixin

  VENDOR_TYPES = {
    # DB            Displayed
    "microsoft"       => "Microsoft",
    "redhat"          => "RedHat",
    "vmware"          => "VMware",
    "openstack_infra" => "OpenStack Infrastructure",
    "unknown"         => "Unknown",
    nil               => "Unknown",
  }

  HOST_DISCOVERY_TYPES = {
    'vmware' => 'esx',
    'ipmi'   => 'ipmi'
  }

  HOST_CREATE_OS_TYPES = {
    'VMware ESX' => 'linux_generic',
    # 'Microsoft Hyper-V' => 'windows_generic'
  }

  validates_presence_of     :name
  validates_presence_of     :hostname, :if => :hostname_required?
  validates_uniqueness_of   :name
  validates_inclusion_of    :user_assigned_os, :in => ["linux_generic", "windows_generic", nil]
  validates_inclusion_of    :vmm_vendor, :in => VENDOR_TYPES.values

  belongs_to                :ext_management_system, :foreign_key => "ems_id"
  belongs_to                :ems_cluster
  has_one                   :operating_system, :dependent => :destroy
  has_one                   :hardware, :dependent => :destroy
  has_many                  :vms_and_templates, :dependent => :nullify
  has_many                  :vms
  has_many                  :miq_templates
  has_one                   :miq_proxy, :dependent => :destroy
  has_and_belongs_to_many   :storages
  has_many                  :switches, :dependent => :destroy
  has_many                  :patches, :dependent => :destroy
  has_many                  :system_services, :dependent => :destroy
  has_many                  :host_services, :class_name => "SystemService", :foreign_key => "host_id"

  has_many                  :metrics,        :as => :resource  # Destroy will be handled by purger
  has_many                  :metric_rollups, :as => :resource  # Destroy will be handled by purger
  has_many                  :vim_performance_states, :as => :resource  # Destroy will be handled by purger

  has_many                  :ems_events, :class_name => "EmsEvent",
    :finder_sql  => lambda { |_| EmsEvent.where("host_id = ? OR dest_host_id = ?", id, id).order(:timestamp).to_sql },
    :counter_sql => lambda { |_| EmsEvent.where("host_id = ? OR dest_host_id = ?", id, id).select("COUNT(*)").to_sql }
  has_many                  :ems_events_src, :class_name => "EmsEvent"
  has_many                  :ems_events_dest, :class_name => "EmsEvent", :foreign_key => :dest_host_id

  has_many                  :policy_events, :order => "timestamp"
  has_many                  :guest_applications, :dependent => :destroy

  has_many                  :filesystems, :as => :resource, :dependent => :destroy
  has_many                  :directories, :as => :resource, :class_name => "Filesystem", :conditions => "rsc_type = 'dir'"
  has_many                  :files,       :as => :resource, :class_name => "Filesystem", :conditions => "rsc_type = 'file'"

  # Accounts - Users and Groups
  has_many                  :accounts, :dependent => :destroy
  has_many                  :users, :class_name => "Account", :foreign_key => "host_id", :conditions => "accttype = 'user'"
  has_many                  :groups, :class_name => "Account", :foreign_key => "host_id", :conditions => "accttype = 'group'"

  has_many                  :advanced_settings, :as => :resource, :dependent => :destroy

  has_many                  :miq_alert_statuses, :dependent => :destroy, :as => :resource

  has_one                   :miq_cim_instance, :as => :vmdb_obj, :dependent => :destroy

  serialize                 :settings

  # TODO: Remove all callers of address
  alias_attribute :address, :hostname

  def settings
    super || self.settings = VMDB::Config.new("hostdefaults").get(:host)
  end

  include SerializedEmsRefObjMixin
  include ProviderObjectMixin

  include WebServiceAttributeMixin
  include EventMixin

  include CustomAttributeMixin
  has_many :ems_custom_attributes, :as => :resource, :dependent => :destroy, :class_name => "CustomAttribute", :conditions => "source = 'VC'"

  acts_as_miq_taggable
  include ReportableMixin

  virtual_column :os_image_name,                :type => :string,      :uses => [:operating_system, :hardware]
  virtual_column :platform,                     :type => :string,      :uses => [:operating_system, :hardware]
  virtual_column :v_owning_cluster,             :type => :string,      :uses => :ems_cluster
  virtual_column :v_owning_datacenter,          :type => :string,      :uses => :all_relationships
  virtual_column :v_owning_folder,              :type => :string,      :uses => :all_relationships
  virtual_column :v_total_storages,             :type => :integer,     :uses => :storages
  virtual_column :v_total_vms,                  :type => :integer,     :uses => :vms
  virtual_column :v_total_miq_templates,        :type => :integer,     :uses => :miq_templates
  virtual_column :total_vcpus,                  :type => :integer
  virtual_column :total_cores,                  :type => :integer
  virtual_column :ram_size,                     :type => :integer
  virtual_column :enabled_inbound_ports,        :type => :numeric_set  # The following are not set to use anything
  virtual_column :enabled_outbound_ports,       :type => :numeric_set  # because get_ports ends up re-querying the
  virtual_column :enabled_udp_inbound_ports,    :type => :numeric_set  # database anyway.
  virtual_column :enabled_udp_outbound_ports,   :type => :numeric_set
  virtual_column :enabled_tcp_inbound_ports,    :type => :numeric_set
  virtual_column :enabled_tcp_outbound_ports,   :type => :numeric_set
  virtual_column :all_enabled_ports,            :type => :numeric_set
  virtual_column :service_names,                :type => :string_set,  :uses => :system_services
  virtual_column :enabled_run_level_0_services, :type => :string_set,  :uses => :host_services
  virtual_column :enabled_run_level_1_services, :type => :string_set,  :uses => :host_services
  virtual_column :enabled_run_level_2_services, :type => :string_set,  :uses => :host_services
  virtual_column :enabled_run_level_3_services, :type => :string_set,  :uses => :host_services
  virtual_column :enabled_run_level_4_services, :type => :string_set,  :uses => :host_services
  virtual_column :enabled_run_level_5_services, :type => :string_set,  :uses => :host_services
  virtual_column :enabled_run_level_6_services, :type => :string_set,  :uses => :host_services
  virtual_column :last_scan_on,                 :type => :time,        :uses => :last_drift_state_timestamp
  virtual_column :v_annotation,                 :type => :string,      :uses => :hardware
  virtual_column :ipmi_enabled,                 :type => :boolean

  virtual_has_many   :resource_pools,                               :uses => :all_relationships
  virtual_has_many   :lans,                                         :uses => {:switches => :lans}
  virtual_has_many   :miq_scsi_luns,                                :uses => {:hardware => {:storage_adapters => {:miq_scsi_targets => :miq_scsi_luns}}}
  virtual_has_many   :processes,       :class_name => "OsProcess",  :uses => {:operating_system => :processes}
  virtual_has_many   :event_logs,                                   :uses => {:operating_system => :event_logs}
  virtual_has_many   :firewall_rules,                               :uses => {:operating_system => :firewall_rules}

  virtual_has_many  :base_storage_extents, :class_name => "CimStorageExtent"
  virtual_has_many  :storage_systems,      :class_name => "CimComputerSystem"
  virtual_has_many  :file_shares,          :class_name => 'SniaFileShare'
  virtual_has_many  :storage_volumes,      :class_name => 'CimStorageVolume'
  virtual_has_many  :logical_disks,        :class_name => 'CimLogicalDisk'

  alias datastores storages    # Used by web-services to return datastores as the property name

  alias parent_cluster ems_cluster
  alias owning_cluster ems_cluster

  include RelationshipMixin
  self.default_relationship_type = "ems_metadata"

  include DriftStateMixin
  alias last_scan_on last_drift_state_timestamp

  include UuidMixin
  include MiqPolicyMixin
  include AlertMixin
  include Metric::CiMixin
  include FilterableMixin
  include AuthenticationMixin
  include AsyncDeleteMixin
  include ComplianceMixin
  include VimConnectMixin

  before_create :make_smart
  after_save    :process_events

  def authentication_check_role
    'smartstate'
  end

  def to_s
    self.name
  end

  def v_annotation
    return nil if self.hardware.nil?
    self.hardware.annotation
  end

  def hostname_required?
    self.vmm_vendor == "vmware"
  end

  # host settings
  def autoscan
    self.settings[:autoscan]
  end
  def autoscan=(switch)<commit_msg>hostname_required? and validation of hostname is no longer needed.<commit_after>$:.push("#{File.dirname(__FILE__)}/../../../lib/util/xml")
$:.push(File.expand_path(File.join(Rails.root, %w{.. lib util win32})))
$:.push("#{File.dirname(__FILE__)}/../../../lib/metadata/linux")

require 'ostruct'
require 'MiqSockUtil'
require 'xml_utils'
require 'cgi'               # Used for URL encoding/decoding
require 'LinuxUsers'
require 'LinuxUtils'

$:.push("#{File.dirname(__FILE__)}/../../../lib/metadata/ScanProfile")
require 'HostScanProfiles'

class Host < ActiveRecord::Base
  include NewWithTypeStiMixin

  VENDOR_TYPES = {
    # DB            Displayed
    "microsoft"       => "Microsoft",
    "redhat"          => "RedHat",
    "vmware"          => "VMware",
    "openstack_infra" => "OpenStack Infrastructure",
    "unknown"         => "Unknown",
    nil               => "Unknown",
  }

  HOST_DISCOVERY_TYPES = {
    'vmware' => 'esx',
    'ipmi'   => 'ipmi'
  }

  HOST_CREATE_OS_TYPES = {
    'VMware ESX' => 'linux_generic',
    # 'Microsoft Hyper-V' => 'windows_generic'
  }

  validates_presence_of     :name
  validates_uniqueness_of   :name
  validates_inclusion_of    :user_assigned_os, :in => ["linux_generic", "windows_generic", nil]
  validates_inclusion_of    :vmm_vendor, :in => VENDOR_TYPES.values

  belongs_to                :ext_management_system, :foreign_key => "ems_id"
  belongs_to                :ems_cluster
  has_one                   :operating_system, :dependent => :destroy
  has_one                   :hardware, :dependent => :destroy
  has_many                  :vms_and_templates, :dependent => :nullify
  has_many                  :vms
  has_many                  :miq_templates
  has_one                   :miq_proxy, :dependent => :destroy
  has_and_belongs_to_many   :storages
  has_many                  :switches, :dependent => :destroy
  has_many                  :patches, :dependent => :destroy
  has_many                  :system_services, :dependent => :destroy
  has_many                  :host_services, :class_name => "SystemService", :foreign_key => "host_id"

  has_many                  :metrics,        :as => :resource  # Destroy will be handled by purger
  has_many                  :metric_rollups, :as => :resource  # Destroy will be handled by purger
  has_many                  :vim_performance_states, :as => :resource  # Destroy will be handled by purger

  has_many                  :ems_events, :class_name => "EmsEvent",
    :finder_sql  => lambda { |_| EmsEvent.where("host_id = ? OR dest_host_id = ?", id, id).order(:timestamp).to_sql },
    :counter_sql => lambda { |_| EmsEvent.where("host_id = ? OR dest_host_id = ?", id, id).select("COUNT(*)").to_sql }
  has_many                  :ems_events_src, :class_name => "EmsEvent"
  has_many                  :ems_events_dest, :class_name => "EmsEvent", :foreign_key => :dest_host_id

  has_many                  :policy_events, :order => "timestamp"
  has_many                  :guest_applications, :dependent => :destroy

  has_many                  :filesystems, :as => :resource, :dependent => :destroy
  has_many                  :directories, :as => :resource, :class_name => "Filesystem", :conditions => "rsc_type = 'dir'"
  has_many                  :files,       :as => :resource, :class_name => "Filesystem", :conditions => "rsc_type = 'file'"

  # Accounts - Users and Groups
  has_many                  :accounts, :dependent => :destroy
  has_many                  :users, :class_name => "Account", :foreign_key => "host_id", :conditions => "accttype = 'user'"
  has_many                  :groups, :class_name => "Account", :foreign_key => "host_id", :conditions => "accttype = 'group'"

  has_many                  :advanced_settings, :as => :resource, :dependent => :destroy

  has_many                  :miq_alert_statuses, :dependent => :destroy, :as => :resource

  has_one                   :miq_cim_instance, :as => :vmdb_obj, :dependent => :destroy

  serialize                 :settings

  # TODO: Remove all callers of address
  alias_attribute :address, :hostname

  def settings
    super || self.settings = VMDB::Config.new("hostdefaults").get(:host)
  end

  include SerializedEmsRefObjMixin
  include ProviderObjectMixin

  include WebServiceAttributeMixin
  include EventMixin

  include CustomAttributeMixin
  has_many :ems_custom_attributes, :as => :resource, :dependent => :destroy, :class_name => "CustomAttribute", :conditions => "source = 'VC'"

  acts_as_miq_taggable
  include ReportableMixin

  virtual_column :os_image_name,                :type => :string,      :uses => [:operating_system, :hardware]
  virtual_column :platform,                     :type => :string,      :uses => [:operating_system, :hardware]
  virtual_column :v_owning_cluster,             :type => :string,      :uses => :ems_cluster
  virtual_column :v_owning_datacenter,          :type => :string,      :uses => :all_relationships
  virtual_column :v_owning_folder,              :type => :string,      :uses => :all_relationships
  virtual_column :v_total_storages,             :type => :integer,     :uses => :storages
  virtual_column :v_total_vms,                  :type => :integer,     :uses => :vms
  virtual_column :v_total_miq_templates,        :type => :integer,     :uses => :miq_templates
  virtual_column :total_vcpus,                  :type => :integer
  virtual_column :total_cores,                  :type => :integer
  virtual_column :ram_size,                     :type => :integer
  virtual_column :enabled_inbound_ports,        :type => :numeric_set  # The following are not set to use anything
  virtual_column :enabled_outbound_ports,       :type => :numeric_set  # because get_ports ends up re-querying the
  virtual_column :enabled_udp_inbound_ports,    :type => :numeric_set  # database anyway.
  virtual_column :enabled_udp_outbound_ports,   :type => :numeric_set
  virtual_column :enabled_tcp_inbound_ports,    :type => :numeric_set
  virtual_column :enabled_tcp_outbound_ports,   :type => :numeric_set
  virtual_column :all_enabled_ports,            :type => :numeric_set
  virtual_column :service_names,                :type => :string_set,  :uses => :system_services
  virtual_column :enabled_run_level_0_services, :type => :string_set,  :uses => :host_services
  virtual_column :enabled_run_level_1_services, :type => :string_set,  :uses => :host_services
  virtual_column :enabled_run_level_2_services, :type => :string_set,  :uses => :host_services
  virtual_column :enabled_run_level_3_services, :type => :string_set,  :uses => :host_services
  virtual_column :enabled_run_level_4_services, :type => :string_set,  :uses => :host_services
  virtual_column :enabled_run_level_5_services, :type => :string_set,  :uses => :host_services
  virtual_column :enabled_run_level_6_services, :type => :string_set,  :uses => :host_services
  virtual_column :last_scan_on,                 :type => :time,        :uses => :last_drift_state_timestamp
  virtual_column :v_annotation,                 :type => :string,      :uses => :hardware
  virtual_column :ipmi_enabled,                 :type => :boolean

  virtual_has_many   :resource_pools,                               :uses => :all_relationships
  virtual_has_many   :lans,                                         :uses => {:switches => :lans}
  virtual_has_many   :miq_scsi_luns,                                :uses => {:hardware => {:storage_adapters => {:miq_scsi_targets => :miq_scsi_luns}}}
  virtual_has_many   :processes,       :class_name => "OsProcess",  :uses => {:operating_system => :processes}
  virtual_has_many   :event_logs,                                   :uses => {:operating_system => :event_logs}
  virtual_has_many   :firewall_rules,                               :uses => {:operating_system => :firewall_rules}

  virtual_has_many  :base_storage_extents, :class_name => "CimStorageExtent"
  virtual_has_many  :storage_systems,      :class_name => "CimComputerSystem"
  virtual_has_many  :file_shares,          :class_name => 'SniaFileShare'
  virtual_has_many  :storage_volumes,      :class_name => 'CimStorageVolume'
  virtual_has_many  :logical_disks,        :class_name => 'CimLogicalDisk'

  alias datastores storages    # Used by web-services to return datastores as the property name

  alias parent_cluster ems_cluster
  alias owning_cluster ems_cluster

  include RelationshipMixin
  self.default_relationship_type = "ems_metadata"

  include DriftStateMixin
  alias last_scan_on last_drift_state_timestamp

  include UuidMixin
  include MiqPolicyMixin
  include AlertMixin
  include Metric::CiMixin
  include FilterableMixin
  include AuthenticationMixin
  include AsyncDeleteMixin
  include ComplianceMixin
  include VimConnectMixin

  before_create :make_smart
  after_save    :process_events

  def authentication_check_role
    'smartstate'
  end

  def to_s
    self.name
  end

  def v_annotation
    return nil if self.hardware.nil?
    self.hardware.annotation
  end

  # host settings
  def autoscan
    self.settings[:autoscan]
  end
  def autoscan=(switch)
{'fraction_non_alphanumeric': 0.10936046829695278, 'fraction_numerical': 0.0009847365829640572, 'mean_word_length': 2.876988335100742, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 252, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 4}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4405285', 'n_tokens_mistral': 5793, 'n_tokens_neox': 5583, 'n_words': 1198}