foreman_discovery 1.4.1 → 2.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +5 -13
  2. data/README.md +52 -96
  3. data/app/controllers/api/v2/discovered_hosts_controller.rb +104 -3
  4. data/app/controllers/api/v2/discovery_rules_controller.rb +79 -0
  5. data/app/controllers/concerns/foreman/controller/discovered_extensions.rb +55 -0
  6. data/app/controllers/discovered_hosts_controller.rb +82 -19
  7. data/app/controllers/discovery_rules_controller.rb +73 -0
  8. data/app/helpers/discovered_hosts_helper.rb +18 -6
  9. data/app/helpers/discovery_rules_helper.rb +36 -0
  10. data/app/lib/puppet_fact_parser_extensions.rb +9 -3
  11. data/app/models/concerns/discovery_subnet.rb +7 -0
  12. data/app/models/discovery_attribute_set.rb +8 -0
  13. data/app/models/discovery_rule.rb +24 -0
  14. data/app/models/host/discovered.rb +64 -7
  15. data/app/models/host/managed_extensions.rb +3 -8
  16. data/app/models/hostgroup_extensions.rb +7 -0
  17. data/app/models/setting/discovered.rb +14 -0
  18. data/app/overrides/subnet_form_with_discovery_proxy.rb +9 -0
  19. data/app/views/api/v2/discovered_hosts/auto_provision.json.rabl +3 -0
  20. data/app/views/api/v2/discovered_hosts/auto_provision_all.json.rabl +3 -0
  21. data/app/views/api/v2/discovered_hosts/main.json.rabl +1 -1
  22. data/app/views/api/v2/discovery_rules/base.json.rabl +3 -0
  23. data/app/views/api/v2/discovery_rules/index.json.rabl +3 -0
  24. data/app/views/api/v2/discovery_rules/main.json.rabl +5 -0
  25. data/app/views/api/v2/discovery_rules/show.json.rabl +3 -0
  26. data/app/views/dashboard/_discovery_widget.html.erb +5 -11
  27. data/app/views/dashboard/_discovery_widget_host_list.html.erb +17 -0
  28. data/app/views/discovered_hosts/_discovered_host.html.erb +12 -0
  29. data/app/views/discovered_hosts/_discovered_hosts_list.html.erb +11 -2
  30. data/app/views/discovered_hosts/index.html.erb +1 -0
  31. data/app/views/discovery_rules/_form.html.erb +14 -0
  32. data/app/views/discovery_rules/edit.html.erb +3 -0
  33. data/app/views/discovery_rules/index.html.erb +26 -0
  34. data/app/views/discovery_rules/new.html.erb +3 -0
  35. data/config/routes.rb +19 -0
  36. data/db/migrate/20141107091416_create_discovery_rules.rb +15 -0
  37. data/db/migrate/20141107091417_add_discovery_rule_to_host.rb +9 -0
  38. data/db/migrate/20141126165451_add_discovery_id_to_subnet.rb +9 -0
  39. data/db/migrate/20141223101707_create_discovery_attribute_sets.rb +14 -0
  40. data/db/migrate/20141223142759_fill_discovery_attribute_sets_for_existing_hosts.rb +8 -0
  41. data/db/seeds.d/60_discovery_proxy_feature.rb +2 -0
  42. data/lib/discovery.rake +0 -82
  43. data/lib/foreman_discovery/engine.rb +81 -14
  44. data/lib/foreman_discovery/proxy_operations.rb +18 -0
  45. data/lib/foreman_discovery/version.rb +1 -1
  46. data/locale/de/LC_MESSAGES/foreman_discovery.mo +0 -0
  47. data/locale/de/foreman_discovery.po +1 -1
  48. data/locale/en_GB/LC_MESSAGES/foreman_discovery.mo +0 -0
  49. data/locale/en_GB/foreman_discovery.po +1 -1
  50. data/locale/es/LC_MESSAGES/foreman_discovery.mo +0 -0
  51. data/locale/es/foreman_discovery.po +3 -3
  52. data/locale/fr/LC_MESSAGES/foreman_discovery.mo +0 -0
  53. data/locale/fr/foreman_discovery.po +1 -1
  54. data/locale/gl/LC_MESSAGES/foreman_discovery.mo +0 -0
  55. data/locale/gl/foreman_discovery.po +1 -1
  56. data/locale/it/LC_MESSAGES/foreman_discovery.mo +0 -0
  57. data/locale/it/foreman_discovery.po +1 -1
  58. data/locale/ja/LC_MESSAGES/foreman_discovery.mo +0 -0
  59. data/locale/ja/foreman_discovery.po +1 -1
  60. data/locale/ko/LC_MESSAGES/foreman_discovery.mo +0 -0
  61. data/locale/ko/foreman_discovery.po +1 -1
  62. data/locale/pt_BR/LC_MESSAGES/foreman_discovery.mo +0 -0
  63. data/locale/pt_BR/foreman_discovery.po +1 -1
  64. data/locale/ru/LC_MESSAGES/foreman_discovery.mo +0 -0
  65. data/locale/ru/foreman_discovery.po +1 -1
  66. data/locale/sv_SE/LC_MESSAGES/foreman_discovery.mo +0 -0
  67. data/locale/sv_SE/foreman_discovery.po +1 -1
  68. data/locale/zh_CN/LC_MESSAGES/foreman_discovery.mo +0 -0
  69. data/locale/zh_CN/foreman_discovery.po +1 -1
  70. data/locale/zh_TW/LC_MESSAGES/foreman_discovery.mo +0 -0
  71. data/locale/zh_TW/foreman_discovery.po +1 -1
  72. data/test/factories/discovery_rule_related.rb +20 -0
  73. data/test/functional/api/v2/discovered_hosts_controller_test.rb +81 -0
  74. data/test/functional/api/v2/discovery_rules_controller_test.rb +51 -0
  75. data/test/functional/discovered_hosts_controller_test.rb +96 -3
  76. data/test/functional/discovery_rules_controller_test.rb +62 -0
  77. data/test/test_helper.rb +0 -1
  78. data/test/unit/discovered_extensions_test.rb +106 -0
  79. data/test/unit/discovery_attribute_set_test.rb +43 -0
  80. data/test/unit/facts.json +4 -1
  81. data/test/unit/host_discovered_test.rb +44 -4
  82. metadata +100 -75
  83. data/Rakefile +0 -110
  84. data/lib/foreman_discovery/facts.rb +0 -12
@@ -1,14 +1,19 @@
1
- require 'foreman_discovery/facts'
1
+ require 'foreman_discovery/proxy_operations'
2
2
 
3
3
  class Host::Discovered < ::Host::Base
4
+ include ScopedSearchExtensions
4
5
 
5
6
  belongs_to :location
6
7
  belongs_to :organization
7
8
  belongs_to :subnet
8
9
  belongs_to :hostgroup
10
+ has_one :discovery_attribute_set, :foreign_key => :host_id, :dependent => :destroy
9
11
 
10
- validates :mac, :uniqueness => true, :format => {:with => Net::Validations::MAC_REGEXP}, :presence => true
12
+ validates :mac, :uniqueness => true, :mac_address => true, :presence => true
11
13
  validates :ip, :format => {:with => Net::Validations::IP_REGEXP}, :uniqueness => true
14
+ validates :discovery_attribute_set, :presence => true
15
+
16
+ delegate :memory, :cpu_count, :disk_count, :disks_size, :to => :discovery_attribute_set
12
17
 
13
18
  scoped_search :on => :name, :complete_value => true, :default_order => true
14
19
  scoped_search :on => :last_report, :complete_value => true
@@ -19,6 +24,10 @@ class Host::Discovered < ::Host::Base
19
24
  scoped_search :in => :location, :on => :name, :rename => :location, :complete_value => true if SETTINGS[:locations_enabled]
20
25
  scoped_search :in => :organization, :on => :name, :rename => :organization, :complete_value => true if SETTINGS[:organizations_enabled]
21
26
  scoped_search :in => :subnet, :on => :network, :complete_value => true, :rename => :subnet
27
+ scoped_search :in => :discovery_attribute_set, :on => :cpu_count, :rename => :cpu_count, :complete_value => true, :only_explicit => true
28
+ scoped_search :in => :discovery_attribute_set, :on => :memory, :rename => :memory, :complete_value => true, :only_explicit => true
29
+ scoped_search :in => :discovery_attribute_set, :on => :disk_count, :rename => :disk_count, :complete_value => true, :only_explicit => true
30
+ scoped_search :in => :discovery_attribute_set, :on => :disks_size, :rename => :disks_size, :complete_value => true, :only_explicit => true
22
31
 
23
32
  default_scope lambda {
24
33
  org = Organization.current
@@ -31,8 +40,11 @@ class Host::Discovered < ::Host::Base
31
40
 
32
41
  def self.import_host_and_facts facts
33
42
  raise(::Foreman::Exception.new(N_("Invalid facts, must be a Hash"))) unless facts.is_a?(Hash)
34
- fact_name = Setting[:discovery_fact] || 'macaddress'
35
- hostname = facts[fact_name].try(:downcase).try(:gsub,/:/,'').try(:sub,/^/,'mac')
43
+ fact_name = Setting[:discovery_fact] || 'discovery_bootif'
44
+ prefix_from_settings = Setting[:discovery_prefix]
45
+ hostname_prefix = prefix_from_settings if prefix_from_settings.present? && prefix_from_settings.match(/^[a-zA-Z].*/)
46
+ hostname_prefix ||= 'mac'
47
+ hostname = facts[fact_name].try(:downcase).try(:gsub,/:/,'').try(:sub,/^/, hostname_prefix)
36
48
  raise(::Foreman::Exception.new(N_("Invalid facts: hash does not contain the required fact '%s'"), fact_name)) unless hostname
37
49
  raise(::Foreman::Exception.new(N_("Invalid facts: hash does not contain IP address"))) unless facts['ipaddress']
38
50
 
@@ -83,26 +95,71 @@ class Host::Discovered < ::Host::Base
83
95
  importer = super(facts)
84
96
  end
85
97
  self.subnet = Subnet.subnet_for(importer.ip)
98
+ self.discovery_attribute_set = DiscoveryAttributeSet.where(:host_id => id).first_or_create
99
+ self.discovery_attribute_set.update_attributes(import_from_facts)
86
100
  self.save
87
101
  end
88
102
 
103
+ def import_from_facts(facts = self.facts_hash)
104
+ cpu_count = facts['physicalprocessorcount'].to_i rescue 0
105
+ memory = facts['memorysize_mb'].to_f.ceil rescue 0
106
+ disks = facts.select { |key, value| key.to_s =~ /blockdevice.*_size/ }
107
+ disks_size = 0
108
+ disk_count = 0
109
+
110
+ if disks.any?
111
+ disks.values.each { |size| disks_size += (size.to_f rescue 0) }
112
+ disk_count = disks.size
113
+ disks_size = disks_size.ceil
114
+ end
115
+
116
+ {:cpu_count => cpu_count, :memory => memory, :disk_count => disk_count, :disks_size => disks_size}
117
+ end
118
+
89
119
  # no need to store anything in the db if the password is our default
90
120
  def root_pass
91
121
  read_attribute(:root_pass).blank? ? (hostgroup.try(:root_pass) || Setting[:root_pass]) : read_attribute(:root_pass)
92
122
  end
93
123
 
124
+ def proxy_url
125
+ if subnet.present? && subnet.discovery.present?
126
+ { :url => subnet.discovery.url + "/discovery/#{self.ip}", :type => 'proxy'}
127
+ else
128
+ { :url => "http://#{self.ip}:8443", :type => 'foreman' }
129
+ end
130
+ end
131
+
94
132
  def refresh_facts
95
133
  # TODO: Can we rely on self.ip? The lease might expire/change....
96
134
  begin
97
- logger.debug "retrieving facts from proxy on ip: #{self.ip}"
98
- facts = ForemanDiscovery::Facts.new(:url => "http://#{self.ip}:8443").facts
135
+ logger.debug "retrieving facts from proxy from url: #{proxy_url[:url]}"
136
+ facts = ForemanDiscovery::ProxyOperations.new(:url => proxy_url[:url], :operation => 'facts').parse_get_operation
99
137
  rescue Exception => e
100
- raise _("Could not get facts from proxy: %s") % e
138
+ raise _("Could not get facts from proxy %{url}: %{error}") % {:url => proxy_url[:url], :error => e}
101
139
  end
102
140
 
103
141
  return self.class.import_host_and_facts facts
104
142
  end
105
143
 
144
+ def reboot
145
+ logger.info "ForemanDiscovery: Rebooting #{name}"
146
+ proxy_url = self.proxy_url
147
+
148
+ if proxy_url[:type] == 'proxy'
149
+ status = ForemanDiscovery::ProxyOperations.new(:url => proxy_url[:url], :operation => 'reboot').parse_put_operation
150
+ else
151
+ status = ::ProxyAPI::BMC.new(:url => "http://#{self.ip}:8443").power :action => "cycle"
152
+ end
153
+
154
+ msg = status ? 'successful' : 'failed'
155
+ logger.info "ForemanDiscovery: reboot result: #{msg}"
156
+ status
157
+ rescue => e
158
+ logger.info "ForemanDiscovery: reboot result: failed"
159
+ logger.warn e.backtrace.join('\n')
160
+ raise e
161
+ end
162
+
106
163
  def self.model_name
107
164
  ActiveModel::Name.new(Host)
108
165
  end
@@ -4,6 +4,8 @@ module Host::ManagedExtensions
4
4
  included do
5
5
  # execute standard callbacks
6
6
  after_validation :queue_reboot
7
+
8
+ belongs_to :discovery_rule
7
9
  end
8
10
 
9
11
  def queue_reboot
@@ -14,14 +16,7 @@ module Host::ManagedExtensions
14
16
  end
15
17
 
16
18
  def setReboot
17
- logger.info "ForemanDiscovery: Rebooting #{name} as its being discovered and assigned"
18
- if ::ProxyAPI::BMC.new(:url => "http://#{old.try(:ip) || ip}:8443").power :action => "cycle"
19
- logger.info "ForemanDiscovery: reboot result: successful"
20
- else
21
- logger.info "ForemanDiscovery: reboot result: failed"
22
- end
23
- rescue => e
24
- failure _("Failed to reboot: %s") % e.message
19
+ old.becomes(Host::Discovered).reboot
25
20
  end
26
21
 
27
22
  def delReboot
@@ -0,0 +1,7 @@
1
+ module HostgroupExtensions
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ has_many :discovery_rules
6
+ end
7
+ end
@@ -1,6 +1,7 @@
1
1
  class Setting::Discovered < ::Setting
2
2
  BLANK_ATTRS << "discovery_location"
3
3
  BLANK_ATTRS << "discovery_organization"
4
+ BLANK_ATTRS << "discovery_fact_column"
4
5
 
5
6
  def self.load_defaults
6
7
  # Check the table exists
@@ -9,6 +10,19 @@ class Setting::Discovered < ::Setting
9
10
  Setting.transaction do
10
11
  [
11
12
  self.set('discovery_fact', _("The default fact name to use for the MAC of the system"), "discovery_bootif"),
13
+ self.set('discovery_auto', _("Automatically provision newly discovered hosts, according to the provisioning rules"), false),
14
+ ].compact.each { |s| self.create s.update(:category => "Setting::Discovered")}
15
+ end
16
+
17
+ Setting.transaction do
18
+ [
19
+ self.set('discovery_prefix', _("The default prefix to use for the host name, must start with a letter"), "mac"),
20
+ ].compact.each { |s| self.create s.update(:category => "Setting::Discovered")}
21
+ end
22
+
23
+ Setting.transaction do
24
+ [
25
+ self.set('discovery_fact_column', _("Show fact as an extra column in the discovered hosts list"), ""),
12
26
  ].compact.each { |s| self.create s.update(:category => "Setting::Discovered")}
13
27
  end
14
28
 
@@ -0,0 +1,9 @@
1
+ selector_text = " <%= select_f f, :discovery_id, SmartProxy.with_features('Discovery'), :id, :name,
2
+ {:include_blank => _('None')},
3
+ :label => _('Discovery Proxy'),
4
+ :help_inline => _('Discovery Proxy to use within this subnet for managing connection to discovered hosts') %>"
5
+
6
+ Deface::Override.new(:virtual_path => "subnets/_form",
7
+ :name => "add_discovery_proxy_to_subnet",
8
+ :insert_bottom => 'div#proxies',
9
+ :text => selector_text)
@@ -0,0 +1,3 @@
1
+ object @discovered_host
2
+
3
+ extends "api/v2/hosts/main"
@@ -0,0 +1,3 @@
1
+ object @discovered_host
2
+
3
+ extends "api/v2/hosts/main"
@@ -2,7 +2,7 @@ object @discovered_host
2
2
 
3
3
  extends "api/v2/discovered_hosts/base"
4
4
 
5
- attributes :ip, :mac, :last_report, :subnet_id, :subnet_name
5
+ attributes :ip, :mac, :last_report, :subnet_id, :subnet_name, :cpu, :memory, :disk_count, :disks_size
6
6
 
7
7
  if SETTINGS[:organizations_enabled]
8
8
  attributes :organization_id, :organization_name
@@ -0,0 +1,3 @@
1
+ object @discovery_rule
2
+
3
+ attributes :id, :name
@@ -0,0 +1,3 @@
1
+ collection @discovery_rules
2
+
3
+ extends "api/v2/discovery_rules/main"
@@ -0,0 +1,5 @@
1
+ object @discovery_rule
2
+
3
+ extends "api/v2/discovery_rules/base"
4
+
5
+ attributes :name, :enabled, :hostgroup_id, :hostname, :max_count, :priority, :search
@@ -0,0 +1,3 @@
1
+ object @discovery_rule
2
+
3
+ extends "api/v2/discovery_rules/main"
@@ -1,16 +1,10 @@
1
1
  <h4 class="ca"><%= _('Discovered Host Pool') %> - <%= @current_permission %></h4>
2
- <% all_hosts = Host::Discovered.search_for '' %>
2
+ <% all_hosts = Host::Discovered.includes(:model).includes(:discovery_attribute_set).scoped %>
3
3
  <% hosts = all_hosts.limit(5) %>
4
4
  <% if hosts.empty? %>
5
- <p class="ca"><%= _("No discovered hosts available") %></p>
5
+ <p class="ca"><%= _("No discovered hosts available") %></p>
6
6
  <% else %>
7
- <table class="table table-striped ellipsis">
8
- <% hosts.each do |host| %>
9
- <tr>
10
- <td><%= link_to h(host.name), discovered_host_path(host) %></td>
11
- <td><%= host.ip %></td>
12
- </tr>
13
- <% end %>
14
- </table>
15
- <p class="ca"><%= link_to n_("Total pool size","Total pool size", all_hosts.size), discovered_hosts_path %> - <%= all_hosts.size %> </p>
7
+ <%= render :partial => 'discovery_widget_host_list', :locals => { :hosts => hosts } %>
8
+ <p class="ca"><%= link_to n_("Total pool size", "Total pool size", all_hosts.size), discovered_hosts_path %>
9
+ - <%= all_hosts.size %> </p>
16
10
  <% end %>
@@ -0,0 +1,17 @@
1
+ <table class="table table-striped ellipsis">
2
+ <thead>
3
+ <th><%= _('Host') %></th>
4
+ <th><%= _('Model') %></th>
5
+ <th><%= _('IP Address') %></th>
6
+ <th><%= _('CPU') %></th>
7
+ <th><%= _('Memory') %></th>
8
+ </thead>
9
+ <tbody>
10
+ <% hosts.each do |host| %>
11
+ <tr>
12
+ <%= render :partial => "discovered_hosts/discovered_host", :locals => {
13
+ :host => host, :hide_disk => true } %>
14
+ </tr>
15
+ <% end %>
16
+ </tbody>
17
+ </table>
@@ -0,0 +1,12 @@
1
+ <td><%= link_to h(host.name), discovered_host_path(host) %></td>
2
+ <td class="hidden-tablet hidden-xs"><%= model_name host %></td>
3
+ <td class="hidden-tablet hidden-xs"><%= host.ip %></td>
4
+ <td class="hidden-tablet hidden-xs"><%= discovery_attribute(host, :cpu_count) %></td>
5
+ <td class="hidden-tablet hidden-xs"><%= number_to_human_size(discovery_attribute(host, :memory, 0) * 1024 * 1024) %></td>
6
+ <% unless defined? hide_disk %>
7
+ <td class="hidden-tablet hidden-xs"><%= discovery_attribute(host, :disk_count) %></td>
8
+ <td class="hidden-tablet hidden-xs"><%= number_to_human_size(discovery_attribute(host, :disks_size, 0)) %></td>
9
+ <% if Setting['discovery_fact_column'].present? %>
10
+ <td class="hidden-tablet hidden-xs"><%= host.facts_hash[Setting['discovery_fact_column']] || 'N/A' %></td>
11
+ <% end %>
12
+ <% end %>
@@ -5,6 +5,14 @@
5
5
  <th class="ca"><%= check_box_tag "check_all", "", false, { :onclick => "toggleCheck()", :'check-title' => _("Select all items in this page"), :'uncheck-title'=> _("items selected. Uncheck to Clear") } %></th>
6
6
  <th class=''><%= sort :name, :as => _('Name') %></th>
7
7
  <th class="hidden-tablet hidden-xs"><%= sort :model, :as => _('Model') %></th>
8
+ <th class="hidden-tablet hidden-xs"><%= sort :ip, :as => _('IP Address') %></th>
9
+ <th class="hidden-tablet hidden-xs"><%= sort :cpu_count, :as => _('CPU') %></th>
10
+ <th class="hidden-tablet hidden-xs"><%= sort :memory, :as => _('Memory') %></th>
11
+ <th class="hidden-tablet hidden-xs"><%= sort :disk_count, :as => _('Disk count') %></th>
12
+ <th class="hidden-tablet hidden-xs"><%= sort :disks_size, :as => _('Disks size') %></th>
13
+ <% if Setting['discovery_fact_column'].present? %>
14
+ <th class="hidden-tablet hidden-xs"><%= Setting['discovery_fact_column'].capitalize %></th>
15
+ <% end %>
8
16
  <% if SETTINGS[:locations_enabled] -%>
9
17
  <th class="hidden-tablet hidden-xs"><%= sort :location, :as => _('Location') %></th>
10
18
  <% end -%>
@@ -20,8 +28,7 @@
20
28
  <td class="ca">
21
29
  <%= check_box_tag "host_ids[]", nil, false, :id => "host_ids_#{host.id}", :disabled => !authorized?, :class => 'host_select_boxes', :onclick => 'hostChecked(this)' -%>
22
30
  </td>
23
- <td><%= link_to("#{host}", discovered_host_path(host) ) %> </td>
24
- <td class="hidden-tablet hidden-xs"><%= model_name host %></td>
31
+ <%= render :partial => "discovered_host", :locals => {:host => host} %>
25
32
  <% if SETTINGS[:locations_enabled] -%>
26
33
  <td class="hidden-tablet hidden-xs"><%= host.location.try(:name) %></td>
27
34
  <% end -%>
@@ -33,7 +40,9 @@
33
40
  <td>
34
41
  <%= action_buttons(
35
42
  link_to(_("Provision"), hash_for_edit_discovered_host_path(:id => host)),
43
+ link_to(_("Auto Provision"), hash_for_auto_provision_discovered_host_path(:id => host), :method => :post),
36
44
  link_to(_("Refresh facts"), hash_for_refresh_facts_discovered_host_path(:id => host)),
45
+ link_to(_("Reboot"), hash_for_reboot_discovered_host_path(:id => host), :method => :put),
37
46
  display_delete_if_authorized(hash_for_discovered_host_path(:id => host), :confirm => _("Delete %s?") % host.name, :action => :destroy))%>
38
47
  </td>
39
48
  </tr>
@@ -1,2 +1,3 @@
1
1
  <% title_actions multiple_discovered_hosts_actions_select -%>
2
+ <% title_actions display_link_if_authorized(_("Auto Provision All"), hash_for_auto_provision_all_discovered_hosts_path, {:method => :post, :disabled => @hosts.empty?}) %>
2
3
  <%= render 'discovered_hosts_list' %>
@@ -0,0 +1,14 @@
1
+ <%= form_for @discovery_rule, :url => (@discovery_rule.new_record? ? discovery_rules_path : discovery_rule_path(:id => @discovery_rule.id)) do |f| %>
2
+ <%= base_errors_for @discovery_rule %>
3
+ <%= text_f f, :name %>
4
+ <%= autocomplete_f f, :search,
5
+ :path => "discovered_hosts",
6
+ :control_group_id => 'search_group', :size => 'col-md-9' %>
7
+ <%= select_f f, :hostgroup_id, accessible_hostgroups, :id, :to_label, { :include_blank => false },
8
+ { :help_inline => _('Target host group for this rule with all properties set')} %>
9
+ <%= text_f f, :hostname, :help_inline => _('Target hostname template pattern (empty for MAC)') %>
10
+ <%= text_f f, :max_count, :label => _('Hosts limit'), :help_inline => _('Maximum hosts provisioned with this rule (0 = unlimited)') %>
11
+ <%= text_f f, :priority, :help_inline => _('Rule priority (lower integer means higher priority)') %>
12
+ <%= checkbox_f f, :enabled %>
13
+ <%= submit_or_cancel f %>
14
+ <% end %>
@@ -0,0 +1,3 @@
1
+ <% title _("Edit Discovery Rule") %>
2
+
3
+ <%= render :partial => 'form' %>
@@ -0,0 +1,26 @@
1
+ <% title _("Discovery Rules") %>
2
+ <% title_actions display_link_if_authorized(_("New Rule"), hash_for_new_discovery_rule_path), help_path %>
3
+
4
+ <table class="table table-bordered table-striped table-two-pane">
5
+ <tr>
6
+ <th><%= sort :name, :as => s_("DiscoveryRule|Name") %></th>
7
+ <th><%= sort :priority, :as => s_("DiscoveryRule|Priority") %></th>
8
+ <th><%= sort :search, :as => s_("DiscoveryRule|Query") %></th>
9
+ <th><%= _("Host group") %></th>
10
+ <th><%= _("Hosts/limit") %></th>
11
+ <th><%= sort :enabled, :as => s_("DiscoveryRule|Enabled") %></th>
12
+ <th></th>
13
+ </tr>
14
+ <% for rule in @discovery_rules %>
15
+ <tr>
16
+ <td class='col-md-3'><%= link_to_if_authorized(trunc(rule.name), hash_for_edit_discovery_rule_path(:id => rule).merge(:auth_object => rule, :authorizer => authorizer)) %></td>
17
+ <td><%= rule.priority %></td>
18
+ <td><%= rule.search %></td>
19
+ <td><%= rule.hostgroup.name %></td>
20
+ <td><%= rule.hosts.count %> / <%= rule.max_count %></td>
21
+ <td><%= rule.enabled %></td>
22
+ <td><%= action_buttons(*permitted_discovery_actions(rule)) %></td>
23
+ </tr>
24
+ <% end %>
25
+ </table>
26
+ <%= will_paginate_with_info @discovery_rules %>
@@ -0,0 +1,3 @@
1
+ <% title _("New Discovery Rule") %>
2
+
3
+ <%= render :partial => 'form' %>
@@ -10,6 +10,8 @@ Rails.application.routes.draw do
10
10
  resources :discovered_hosts do
11
11
  member do
12
12
  get 'refresh_facts'
13
+ put 'reboot'
14
+ post 'auto_provision'
13
15
  end
14
16
  collection do
15
17
  get 'multiple_destroy'
@@ -19,18 +21,35 @@ Rails.application.routes.draw do
19
21
  get 'select_multiple_location'
20
22
  post 'update_multiple_location'
21
23
  get 'auto_complete_search'
24
+ post 'auto_provision_all'
22
25
  end
23
26
  end
24
27
  end
25
28
 
29
+ resources :discovery_rules, :except => [:show] do
30
+ member do
31
+ get :enable
32
+ get :disable
33
+ end
34
+ end
35
+
26
36
  ## API
27
37
  namespace :api, :defaults => {:format => 'json'} do
28
38
  scope "(:apiv)", :module => :v2, :defaults => {:apiv => 'v2'}, :apiv => /v1|v2/, :constraints => ApiConstraints.new(:version => 2) do
29
39
  resources :discovered_hosts, :except => [:new, :edit] do
40
+ member do
41
+ post 'auto_provision'
42
+ put 'reboot'
43
+ end
30
44
  collection do
31
45
  post 'facts'
46
+ post 'auto_provision_all'
47
+ end
48
+ member do
49
+ put 'refresh_facts'
32
50
  end
33
51
  end
52
+ resources :discovery_rules, :except => [:new, :edit]
34
53
  end
35
54
  end
36
55
 
@@ -0,0 +1,15 @@
1
+ class CreateDiscoveryRules < ActiveRecord::Migration
2
+ def change
3
+ create_table :discovery_rules do |t|
4
+ t.string :name, :length => 254
5
+ t.string :search, :length => 254
6
+ t.integer :hostgroup_id, :null => false
7
+ t.string :hostname, :length => 254, :default => ''
8
+ t.integer :max_count, :default => 0
9
+ t.integer :priority, :default => 0
10
+ t.boolean :enabled, :default => true, :null => false
11
+
12
+ t.timestamps
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ class AddDiscoveryRuleToHost < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :hosts, :discovery_rule_id, :integer
4
+ end
5
+
6
+ def self.down
7
+ remove_column :hosts, :discovery_rule_id, :integer
8
+ end
9
+ end