foreman_discovery 1.0.0.rc2 → 1.0.0.rc3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md CHANGED
@@ -35,10 +35,17 @@ sudo, as the password prompts may get lost in the ruby->bash forking process.
35
35
 
36
36
  ## Image configuration
37
37
 
38
- The PXE image has no configuration options during build. However, it will attempt to
39
- download `/discovery_init.sh` from your Foreman server and run it. This is entirely
40
- optional - if the server cannot be reached or the file cannot be found, the image
41
- has a fallback script built in.
38
+ The PXE image has two configuration options during build:
39
+
40
+ * By default it will have an automatic login to the 'tc' user and start ssh so you can
41
+ ssh to `tc@<ip>` with password test1234. By specifying `mode=prod` on the rake task,
42
+ you can disable both of these - the image will have no accounts that can be logged in
43
+ * If you need to add additional files to the image, put them in `./additional_build_files/` -
44
+ these will be copied to `/additional_build_files/` in the image
45
+
46
+ Also, it will attempt todownload `/discovery_init.sh` from your Foreman server and run
47
+ it. This is entirely optional - if the server cannot be reached or the file cannot be
48
+ found, the image has a fallback script built in.
42
49
 
43
50
  You can find an example script [here](extra/discovery_init.sh.example) - place your
44
51
  modified version in the `public/` directory on your Foreman server.
@@ -88,7 +95,7 @@ The uploaded hash will appear as a discovered host, and provisioning it should w
88
95
  # Usage
89
96
 
90
97
  Boot a machine using the new PXE config above. It should register with Foreman.
91
- The new Host should show up in `More->Discovered Hosts`. Then select a Discovered Host
98
+ The new Host should show up in `More->Provisioning->Discovered Hosts`. Then select a Discovered Host
92
99
  and choose Provision. You'll be taken to the normal Edit page for a Host, with the
93
100
  discovered data filled in where possible. Fill in the details as normal.
94
101
 
@@ -105,10 +112,12 @@ assign the `:perform_discovery` permission to an existing Role.
105
112
 
106
113
  # TODO
107
114
 
108
- * Add Tests
115
+ * Add more Tests
109
116
  * Add API
110
117
  * Add proper Location/Organization handling (via a Wizard maybe?)
111
118
  * Add per-subnet discovery
119
+ * Rake Task for ISO build
120
+ * Easy way to add custom facts to build/runtime
112
121
 
113
122
  # Copyright
114
123
 
@@ -3,35 +3,50 @@ class DiscoversController < ::ApplicationController
3
3
  include Foreman::Controller::TaxonomyMultiple
4
4
  unloadable
5
5
 
6
+ # Avoid auth for discovered host creation
7
+ skip_before_filter :require_login, :require_ssl, :authorize, :verify_authenticity_token, :set_taxonomy, :session_expiry, :update_activity_time, :only => :create
8
+
6
9
  before_filter :find_by_name, :only => %w[show edit update destroy refresh_facts convert]
7
10
  before_filter :find_multiple, :only => [:multiple_destroy, :submit_multiple_destroy]
8
11
 
9
-
10
12
  helper :hosts
11
13
 
12
14
  layout 'layouts/application'
13
15
 
14
16
  def index
15
17
  hosts = ::Host::Discovered.search_for(params[:search], :order => params[:order])
16
- # This `where` shouldn't be necessary, but randomly the sql query on the line above
17
- # sometimes loses the `where` clause, leading to all Hosts on the Discovery index
18
- @hosts = hosts.where(:type => "Host::Discovered").includes(:model, :location, :organization).paginate :page => params[:page]
19
18
  respond_to do |format|
20
- format.html { }
19
+ format.html { @hosts = hosts.list.paginate :page => params[:page] }
21
20
  format.json { render :json => hosts }
22
21
  end
23
22
  end
24
23
 
24
+ # Importing yaml is restricted to puppetmasters, so instead we take the ip
25
+ # as a parameter and use refresh_facts to get the rest
26
+ def create
27
+ Taxonomy.no_taxonomy_scope do
28
+ imported = Host::Discovered.new(:ip => get_ip_from_env).refresh_facts
29
+ respond_to do |format|
30
+ format.yml {
31
+ if imported
32
+ render :text => _("Imported facts"), :status => 200 and return
33
+ else
34
+ render :text => _("Failed to import facts"), :status => 400
35
+ end
36
+ }
37
+ end
38
+ end
39
+ rescue Exception => e
40
+ logger.warn "Failed to import facts: #{e}"
41
+ render :text => _("Failed to import facts: %s") % (e), :status => 400
42
+ end
43
+
25
44
  def show
26
- respond_to do |format|
27
- format.html {
28
- # filter graph time range
29
- @range = nil
45
+ # filter graph time range
46
+ @range = nil
30
47
 
31
- # summary report text
32
- @report_summary = nil
33
- }
34
- end
48
+ # summary report text
49
+ @report_summary = nil
35
50
  end
36
51
 
37
52
  def destroy
@@ -58,11 +73,52 @@ class DiscoversController < ::ApplicationController
58
73
  else
59
74
  load_vars_for_ajax
60
75
  offer_to_overwrite_conflicts
61
- process_error
76
+ process_error :object => @host, :render => 'hosts/edit'
62
77
  end
63
78
  end
64
79
  end
65
80
 
81
+ def refresh_facts
82
+ if @host.is_a?(::Host::Discovered) and @host.refresh_facts
83
+ process_success :success_msg => "Facts refreshed for #{@host.name}", :success_redirect => :back
84
+ else
85
+ process_error :error_msg => "Failed to refresh facts for #{@host.name}", :redirect => :back
86
+ end
87
+ end
88
+
89
+ def multiple_destroy
90
+ end
91
+
92
+ def submit_multiple_destroy
93
+ # keep all the ones that were not deleted for notification.
94
+ @hosts.delete_if {|host| host.destroy}
95
+
96
+ missed_hosts = @hosts.map(&:name).join('<br/>')
97
+ if @hosts.empty?
98
+ notice "Destroyed selected hosts"
99
+ else
100
+ error "The following hosts were not deleted: #{missed_hosts}"
101
+ end
102
+ redirect_to(discovers_path)
103
+ end
104
+
105
+ def auto_complete_search
106
+ begin
107
+ @items = Host::Discovered.complete_for(params[:search])
108
+ @items = @items.map do |item|
109
+ category = (['and','or','not','has'].include?(item.to_s.sub(/^.*\s+/,''))) ? 'Operators' : ''
110
+ part = item.to_s.sub(/^.*\b(and|or)\b/i) {|match| match.sub(/^.*\s+/,'')}
111
+ completed = item.to_s.chomp(part)
112
+ {:completed => completed, :part => part, :label => item, :category => category}
113
+ end
114
+ rescue ScopedSearch::QueryNotSupported => e
115
+ @items = [{:error =>e.to_s}]
116
+ end
117
+ render :json => @items
118
+ end
119
+
120
+ private
121
+
66
122
  def load_vars_for_ajax
67
123
  return unless @host
68
124
 
@@ -84,14 +140,6 @@ class DiscoversController < ::ApplicationController
84
140
  @host.overwrite = "true" if @host.errors.any? and @host.errors.are_all_conflicts?
85
141
  end
86
142
 
87
- def refresh_facts
88
- if @host.is_a?(::Host::Discovered) and @host.refresh_facts
89
- process_success :success_msg => "Facts refreshed for #{@host.name}", :success_redirect => :back
90
- else
91
- process_error :error_msg => "Failed to refresh facts for #{@host.name}", :redirect => :back
92
- end
93
- end
94
-
95
143
  def find_by_name
96
144
  params[:id].downcase! if params[:id].present?
97
145
  @host = ::Host::Discovered.find_by_id(params[:id])
@@ -117,35 +165,19 @@ class DiscoversController < ::ApplicationController
117
165
  redirect_to discovers_path
118
166
  end
119
167
 
120
- def multiple_destroy
121
- end
168
+ def get_ip_from_env
169
+ # try to find host based on our client ip address
170
+ ip = request.env['REMOTE_ADDR']
122
171
 
123
- def submit_multiple_destroy
124
- # keep all the ones that were not deleted for notification.
125
- @hosts.delete_if {|host| host.destroy}
172
+ # check if someone is asking on behave of another system (load balance etc)
173
+ ip = request.env['HTTP_X_FORWARDED_FOR'] if request.env['HTTP_X_FORWARDED_FOR'].present?
126
174
 
127
- missed_hosts = @hosts.map(&:name).join('<br/>')
128
- if @hosts.empty?
129
- notice "Destroyed selected hosts"
130
- else
131
- error "The following hosts were not deleted: #{missed_hosts}"
132
- end
133
- redirect_to(discovers_path)
134
- end
175
+ # Check for explicit parameter override
176
+ ip = params.delete('ip') if params.include?('ip')
135
177
 
136
- def auto_complete_search
137
- begin
138
- @items = Host::Discovered.complete_for(params[:search])
139
- @items = @items.map do |item|
140
- category = (['and','or','not','has'].include?(item.to_s.sub(/^.*\s+/,''))) ? 'Operators' : ''
141
- part = item.to_s.sub(/^.*\b(and|or)\b/i) {|match| match.sub(/^.*\s+/,'')}
142
- completed = item.to_s.chomp(part)
143
- {:completed => completed, :part => part, :label => item, :category => category}
144
- end
145
- rescue ScopedSearch::QueryNotSupported => e
146
- @items = [{:error =>e.to_s}]
147
- end
148
- render :json => @items
178
+ Rails.logger.info ip.inspect
179
+ # in case we got back multiple ips (see #1619)
180
+ ip = ip.split(',').first
149
181
  end
150
182
 
151
183
  end
@@ -20,16 +20,14 @@ module DiscoversHelper
20
20
  end
21
21
 
22
22
  def multiple_discovers_actions_select
23
- actions = [
24
- ['Delete Hosts', multiple_destroy_discovers_path, 'trash'],
25
- ]
23
+ actions = [['Delete Hosts', multiple_destroy_discovers_path, 'trash']]
26
24
  actions << ['Assign Organization', select_multiple_organization_discovers_path, 'tags'] if SETTINGS[:organizations_enabled]
27
25
  actions << ['Assign Location', select_multiple_location_discovers_path, 'map-marker'] if SETTINGS[:locations_enabled]
28
26
 
29
- content_tag :span, :id => 'submit_multiple', :class => 'fl' do
30
- actions.map do |action|
31
- link_to(icon_text(action[2]), action[1], :title => action[0])
32
- end.join(' ').html_safe
27
+ content_tag :span, :id => 'submit_multiple' do
28
+ select_action_button( _("Select Action"), actions.map do |action|
29
+ link_to(icon_text(action[2], action[0]) , action[1], :class=>'btn', :title => _("%s - The following hosts are about to be changed") % action[0])
30
+ end.flatten)
33
31
  end
34
32
 
35
33
  end
@@ -4,6 +4,7 @@ class Host::Discovered < ::Host::Base
4
4
 
5
5
  belongs_to :location
6
6
  belongs_to :organization
7
+ belongs_to :subnet
7
8
 
8
9
  scoped_search :on => :name, :complete_value => true, :default_order => true
9
10
  scoped_search :on => :last_report, :complete_value => true
@@ -11,6 +12,14 @@ class Host::Discovered < ::Host::Base
11
12
  scoped_search :on => :mac, :complete_value => true
12
13
  scoped_search :in => :model, :on => :name, :complete_value => true, :rename => :model
13
14
  scoped_search :in => :fact_values, :on => :value, :in_key => :fact_names, :on_key => :name, :rename => :facts, :complete_value => true, :only_explicit => true
15
+ scoped_search :in => :location, :on => :name, :rename => :location, :complete_value => true if SETTINGS[:locations_enabled]
16
+ scoped_search :in => :organization, :on => :name, :rename => :organization, :complete_value => true if SETTINGS[:organizations_enabled]
17
+ scoped_search :in => :subnet, :on => :network, :complete_value => true, :rename => :subnet
18
+
19
+ # This `where` shouldn't be necessary, but randomly the sql query on the line above
20
+ # sometimes loses the `where` clause, leading to all Hosts on the Discovery index
21
+ # this seems like a rails bug, TODO: figure out whats really wrong here
22
+ scope :list, lambda { where(:type => "Host::Discovered").includes(:model, :location, :organization) }
14
23
 
15
24
  def self.importHostAndFacts data
16
25
  # data might already be a hash, from refresh_facts
@@ -30,7 +39,7 @@ class Host::Discovered < ::Host::Base
30
39
  end
31
40
 
32
41
  # filter facts
33
- values.reject!{|k,v| k =~ /kernel|operatingsystem|osfamily|ruby|path|time|swap|free|filesystem/i }
42
+ values.reject!{|k,v| k =~ /kernel|operatingsystem|osfamily|ruby|path|time|swap|free|filesystem|version/i }
34
43
 
35
44
  if name
36
45
  h = ::Host::Discovered.find_by_name name
@@ -71,13 +80,14 @@ class Host::Discovered < ::Host::Base
71
80
 
72
81
  def populateFieldsFromFacts facts = self.facts_hash
73
82
  importer = super
83
+ self.subnet = Subnet.subnet_for(importer.ip)
74
84
  self.save
75
85
  end
76
86
 
77
87
  def refresh_facts
78
88
  # TODO: Can we rely on self.ip? The lease might expire/change....
79
89
  begin
80
- logger.debug "retrieving facts from proxy"
90
+ logger.debug "retrieving facts from proxy on ip: #{self.ip}"
81
91
  facts = ForemanDiscovery::Facts.new(:url => "http://#{self.ip}:8443").facts
82
92
  rescue Exception => e
83
93
  raise "Could not get facts from Proxy: #{e}"
@@ -15,7 +15,7 @@ module Host::ManagedExtensions
15
15
 
16
16
  def setReboot
17
17
  logger.info "ForemanDiscovery: Rebooting #{name} as its being discovered and assigned"
18
- if ::ProxyAPI::BMC.new(:url => "http://#{ip}:8443").power :action => "cycle"
18
+ if ::ProxyAPI::BMC.new(:url => "http://#{old.try(:ip) || ip}:8443").power :action => "cycle"
19
19
  logger.info "ForemanDiscovery: reboot result: successful"
20
20
  else
21
21
  logger.info "ForemanDiscovery: reboot result: failed"
@@ -2,7 +2,7 @@
2
2
  <% title 'Discovered Hosts' %>
3
3
  <table class="table table-bordered table-striped table-condensed" >
4
4
  <tr>
5
- <th class="ca"><%= check_box_tag "check_all", "", false, { :onclick => "toggleCheck()", :title => "Select All" } %></th>
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 %></th>
7
7
  <th class="hidden-tablet hidden-phone"><%= sort :model %></th>
8
8
  <% if SETTINGS[:locations_enabled] -%>
@@ -11,6 +11,7 @@
11
11
  <% if SETTINGS[:organizations_enabled] -%>
12
12
  <th class="hidden-tablet hidden-phone"><%= sort :organization %></th>
13
13
  <% end -%>
14
+ <th class="hidden-tablet hidden-phone"><%= sort :subnet, :as => "Subnet" %></th>
14
15
  <th class="hidden-tablet hidden-phone"><%= sort :last_report, :as => "Facts last received" %></th>
15
16
  <th></th>
16
17
  </tr>
@@ -27,6 +28,7 @@
27
28
  <% if SETTINGS[:organizations_enabled] -%>
28
29
  <td class="hidden-tablet hidden-phone"><%= host.organization.try(:name) %></td>
29
30
  <% end -%>
31
+ <td class="hidden-tablet hidden-phone"><%= host.subnet %></td>
30
32
  <td class="hidden-tablet hidden-phone"><%= disc_report_column(host) %></td>
31
33
  <td>
32
34
  <%= action_buttons(
@@ -9,12 +9,10 @@ Foreman::AccessControl.map do |map|
9
9
  end
10
10
 
11
11
  begin
12
- # Add a new role called 'Discovery' if it doesn't exist
13
- Role.transaction do
14
- discovery_role = Role.find_or_create_by_name("Discovery")
15
- if discovery_role.permissions.empty?
16
- discovery_role.update_attribute :permissions, [:perform_discovery]
12
+ # Add a new role called 'Discovery' if it doesn't exist
13
+ Role.transaction do
14
+ role = Role.find_or_create_by_name("Discovery")
15
+ role.update_attribute :permissions, [:perform_discovery] if role.permissions.empty?
17
16
  end
18
- end
19
17
  rescue
20
18
  end
data/extra/build_iso.sh CHANGED
@@ -3,14 +3,21 @@
3
3
  ## Remaster TCL for the Discovery Image
4
4
  # (from http://wiki.tinycorelinux.net/wiki:remastering)
5
5
  #
6
- # This script will build the boot image. You will need squashfs-tools and
6
+ # This script will build the boot image. You will need squashfs-tools and
7
7
  # advancecomp. Run it as root, or with passwordless sudo, or the password prompts
8
8
  # may get lost when the rake task is run.
9
9
 
10
+ # Image type
11
+ MODE=$1
12
+
10
13
  # Setup
11
14
  GEMS="facter json_pure rack rack-protection tilt sinatra"
12
- TGZS="libssl-0.9.8 ruby"
15
+ TGZS="libssl-0.9.8 ruby firmware firmware-bnx2 firmware-broadcom scsi-3.0.21-tinycore dmidecode lldpad"
16
+ if [[ $MODE == 'debug' ]] ; then
17
+ TGZS="$TGZS gcc_libs openssl-1.0.0 openssh"
18
+ fi
13
19
 
20
+ LAUNCH_DIR=`pwd`
14
21
  TOPDIR=`mktemp -d`
15
22
  cd $TOPDIR
16
23
 
@@ -20,6 +27,7 @@ if [ -f /tmp/tcl.iso ]; then
20
27
  cp /tmp/tcl.iso ./tcl.iso
21
28
  else
22
29
  wget http://distro.ibiblio.org/tinycorelinux/4.x/x86/release/Core-current.iso -O tcl.iso
30
+ cp tcl.iso /tmp/tcl.iso
23
31
  fi
24
32
  mkdir loop && mount -oloop tcl.iso loop/
25
33
  cp loop/boot/core.gz loop/boot/vmlinuz .
@@ -28,23 +36,76 @@ umount loop && rmdir loop
28
36
  # Modify basic image:
29
37
  mkdir extract && cd extract
30
38
  zcat $TOPDIR/core.gz | sudo cpio -i -H newc -d
31
- mkdir opt/gems && cd opt/gems
32
- for n in $GEMS ; do gem fetch $n ; done
39
+
40
+ # add link for dmidecode so facter can detect it.
41
+ ln -s /usr/local/sbin/dmidecode usr/sbin/dmidecode
42
+
43
+ # Include static additional files
44
+ mkdir ./additional_build_files
45
+ wget -O ./additional_build_files/ipmi.rb https://github.com/zoide/puppet-ipmi/raw/master/lib/facter/ipmi.rb
46
+ wget -O ./additional_build_files/lldp.rb https://github.com/mfournier/puppet-lldp/raw/master/lib/facter/lldp.rb
47
+ if [ -d $LAUNCH_DIR/additional_build_files ]; then
48
+ echo "including files from $LAUNCH_DIR/additional_build_files"
49
+ cp -r $LAUNCH_DIR/additional_build_files .
50
+ fi
51
+
52
+ # Account/SSH setup
53
+ cd $TOPDIR/extract
54
+ if [[ $MODE == "prod" ]] ; then
55
+ # Prod mode, lock out the accounts
56
+ echo "Prod mode; disabling shell"
57
+ cat > etc/passwd <<EOF
58
+ root:x:0:0:root:/root:/bin/sh
59
+ lp:x:7:7:lp:/var/spool/lpd:/bin/sh
60
+ nobody:x:65534:65534:nobody:/nonexistent:/bin/false
61
+ tc:x:1001:50:Linux User,,,:/home/tc:/bin/sh
62
+ EOF
63
+ cat > etc/shadow <<EOF
64
+ root:*:13525:0:99999:7:::
65
+ lp:*:13510:0:99999:7:::
66
+ nobody:*:13509:0:99999:7:::
67
+ tc:*:15492:0:99999:7:::
68
+ EOF
69
+ sed -i 's/-nl \/sbin\/autologin.*/38400 tty1/' etc/inittab
70
+ else
71
+ echo "Debug mode; enabling SSH"
72
+ echo "" >> opt/bootlocal.sh
73
+ echo "ssh-keygen -t rsa -f /usr/local/etc/ssh/ssh_host_rsa_key -N ''" >> opt/bootlocal.sh
74
+ echo "ssh-keygen -t dsa -f /usr/local/etc/ssh/ssh_host_dsa_key -N ''" >> opt/bootlocal.sh
75
+ echo "ssh-keygen -t ecdsa -f /usr/local/etc/ssh/ssh_host_ecdsa_key -N ''" >> opt/bootlocal.sh
76
+ echo "cp /usr/local/etc/ssh/sshd_config.example /usr/local/etc/ssh/sshd_config" >> opt/bootlocal.sh
77
+ cat > etc/shadow <<EOF
78
+ root:*:13525:0:99999:7:::
79
+ lp:*:13510:0:99999:7:::
80
+ nobody:*:13509:0:99999:7:::
81
+ tc:\$1\$TdSq3t4T\$yCDutSXcI9meEywIoopbu/:15492:0:99999:7:::
82
+ EOF
83
+ echo "/usr/local/sbin/sshd" >> opt/bootlocal.sh
84
+ fi
33
85
 
34
86
  # Build the init script
35
- echo "" >> ../bootlocal.sh
36
- echo "sleep 20" >> ../bootlocal.sh # network can be slow to come up, and we're not in a rush
37
- echo "/opt/foreman_startup.rb" >> ../bootlocal.sh
38
- echo "/opt/discovery_init.sh" >> ../bootlocal.sh
87
+ echo "" >> opt/bootlocal.sh
88
+ echo "sleep 20" >> opt/bootlocal.sh # network can be slow to come up, and we're not in a rush
89
+ echo "/opt/foreman_startup.rb" >> opt/bootlocal.sh
90
+ echo "/opt/discovery_init.sh" >> opt/bootlocal.sh
39
91
 
40
92
  # Get the downloader
41
- wget https://raw.github.com/theforeman/foreman_discovery/master/extra/foreman_startup.rb -O ../foreman_startup.rb
42
- chmod 755 ../foreman_startup.rb
93
+ cp `dirname $0`/foreman_startup.rb opt/foreman_startup.rb
94
+ chmod 755 opt/foreman_startup.rb
95
+
96
+ # Get the gems
97
+ mkdir opt/gems && cd opt/gems
98
+ for n in $GEMS ; do gem fetch $n ; done
43
99
 
44
100
  # Build the fallback script
45
101
  echo "#!/bin/sh" >> ../discovery_init.sh
46
102
  for n in $GEMS ; do echo "gem install -l --no-ri --no-rdoc /opt/gems/`ls *$n-[0-9]*.gem`" >> ../discovery_init.sh ; done
47
- echo "" >> ../bootlocal.sh
103
+ echo "" >> ../discovery_init.sh
104
+ echo 'FACTER_LIB=`gem which facter`' >> ../discovery_init.sh
105
+ echo 'FACTER_PATH=`dirname $FACTER_LIB`' >> ../discovery_init.sh
106
+ echo 'cp /additional_build_files/ipmi.rb $FACTER_PATH/facter/ipmi.rb' >> ../discovery_init.sh
107
+ echo 'cp /additional_build_files/lldp.rb $FACTER_PATH/facter/lldp.rb' >> ../discovery_init.sh
108
+ echo 'cp /additional_build_files/netinfo.rb $FACTER_PATH/facter/netinfo.rb' >> ../discovery_init.sh
48
109
  echo "/usr/share/foreman-proxy/bin/smart-proxy" >> ../discovery_init.sh
49
110
  echo "/usr/share/foreman-proxy/bin/discover_host" >> ../discovery_init.sh
50
111
  chmod 755 ../discovery_init.sh
@@ -87,7 +148,7 @@ mkdir -p ./proxy/usr/share
87
148
  mkdir -p ./proxy/var/run/foreman-proxy
88
149
  mkdir -p ./proxy/var/log/foreman-proxy
89
150
  git clone https://github.com/theforeman/smart-proxy.git ./proxy/usr/share/foreman-proxy
90
- wget https://raw.github.com/theforeman/foreman_discovery/master/extra/discover_host -O ./proxy/usr/share/foreman-proxy/bin/discover_host
151
+ cp `dirname $0`/discover_host ./proxy/usr/share/foreman-proxy/bin/discover_host
91
152
  chmod 755 ./proxy/usr/share/foreman-proxy/bin/discover_host
92
153
  cp ./proxy/usr/share/foreman-proxy/config/settings.yml{.example,}
93
154
  sed -i 's/.*:bmc:.*/:bmc: true/' ./proxy/usr/share/foreman-proxy/config/settings.yml
data/extra/discover_host CHANGED
@@ -4,11 +4,11 @@ require 'fileutils'
4
4
  require 'net/http'
5
5
  require 'net/https'
6
6
  require 'uri'
7
- require 'yaml'
8
7
 
9
- # Would like to not need this...
8
+ # For comparison
10
9
  require 'rubygems'
11
- require 'json'
10
+ require 'facter'
11
+ require 'yaml'
12
12
 
13
13
  def discover_server
14
14
  server = (discover_by_pxe or discover_by_dns)
@@ -45,35 +45,47 @@ def discover_by_dns
45
45
  end
46
46
  end
47
47
 
48
+ def upload
49
+ puts "#{Time.now}: Triggering import of facts from Foreman"
50
+ begin
51
+ uri = URI.parse(discover_server)
52
+ http = Net::HTTP.new(uri.host, uri.port)
53
+ if uri.scheme == 'https' then
54
+ http.use_ssl = true
55
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
56
+ end
57
+ req = Net::HTTP::Post.new("/discovers")
58
+ req.set_form_data({})
59
+ response = http.request(req)
60
+ puts response.body
61
+ rescue Exception => e
62
+ raise "#{Time.now}: Could not send facts to Foreman: #{e}"
63
+ end
64
+ end
65
+
66
+ def write_cache(data)
67
+ File.open('/tmp/proxy_cache', 'w') {|f| f.write(data) }
68
+ end
69
+
70
+ def read_cache
71
+ File.read('/tmp/proxy_cache')
72
+ rescue => e
73
+ "empty cache"
74
+ end
75
+
48
76
  # Main
49
77
 
50
78
  $stdout.reopen("/tmp/proxy-discovery.log", "w")
51
79
  $stderr.reopen("/tmp/proxy-discovery.err", "w")
52
80
 
53
- # Get facts from the Proxy
54
- puts "retrieving facts"
55
- begin
56
- uri = URI.parse("http://localhost:8443/facts")
57
- http = Net::HTTP.new(uri.host, uri.port)
58
- response = http.request(Net::HTTP::Get.new(uri.request_uri))
59
- # Ugly
60
- facts = YAML.dump(JSON.parse(response.body))
61
- rescue Exception => e
62
- raise "Could not get facts from Proxy: #{e}"
63
- end
64
-
65
- puts "Importing facts"
66
- begin
67
- uri = URI.parse(discover_server)
68
- http = Net::HTTP.new(uri.host, uri.port)
69
- if uri.scheme == 'https' then
70
- http.use_ssl = true
71
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
81
+ # loop, but only upload on changes
82
+ while true do
83
+ uninteresting_facts=/kernel|operatingsystem|osfamily|ruby|path|time|swap|free|filesystem|version|selinux/i
84
+ facts = Facter.to_hash.reject! {|k,v| k =~ uninteresting_facts }
85
+ unless YAML.load(read_cache) == facts
86
+ puts "Fact cache invalid, reloading to foreman"
87
+ upload
88
+ write_cache(YAML.dump(facts))
72
89
  end
73
- req = Net::HTTP::Post.new("/fact_values/create?type=Host::Discovered")
74
- req.set_form_data({'facts' => facts})
75
- response = http.request(req)
76
- puts response.body
77
- rescue Exception => e
78
- raise "Could not send facts to Foreman: #{e}"
90
+ sleep 60
79
91
  end
@@ -11,10 +11,7 @@ module DiscoveryHomeHelperPatch
11
11
  # Adds a discovers link to the More menu
12
12
  def setting_options_with_discovers_link
13
13
  choices = setting_options_without_discovers_link
14
- choices += [
15
- [:divider],
16
- ['Discovered Hosts', :discovers]
17
- ]
14
+ choices[2][2].insert(2,['Discovered Hosts', :discovers])
18
15
  authorized_menu_actions(choices)
19
16
  end
20
17
  end
@@ -1,3 +1,3 @@
1
1
  module ForemanDiscovery
2
- VERSION = "1.0.0.rc2"
2
+ VERSION = "1.0.0.rc3"
3
3
  end
data/lib/tasks.rake CHANGED
@@ -11,7 +11,13 @@ END_DESC
11
11
  namespace :discovery do
12
12
  task :build_image => :environment do
13
13
 
14
- verbose = ENV['build_verbose'] && ENV['build_verbose'] != 'false' ? true : false
14
+ verbose = ( ENV['build_verbose'] and ENV['build_verbose'] != 'false' ) ? true : false
15
+ mode = case ENV['mode']
16
+ when /prod/
17
+ "prod"
18
+ else
19
+ "debug"
20
+ end
15
21
 
16
22
  # This requires a lot of root-level actions, lets ensure we have root access
17
23
  if Process.uid == 0 && Process.euid == 0
@@ -39,9 +45,8 @@ namespace :discovery do
39
45
 
40
46
  script=`bundle show foreman_discovery`.strip + '/extra/build_iso.sh'
41
47
  builddir=''
42
- puts 'Building TCL Discovery Image - this may take a while'
43
48
  begin
44
- status = Open4::popen4("#{prefix} #{script}") do |pid, stdin, stdout, stderr|
49
+ status = Open4::popen4("#{prefix} #{script} #{mode}") do |pid, stdin, stdout, stderr|
45
50
  puts "pid : #{ pid }" if verbose
46
51
  stdrout=stdout.read.strip
47
52
  builddir = stdrout.split("\n").delete_if {|x| x !~ /#TMPDIR#/}.to_s.split(' ').last
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreman_discovery
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.rc2
4
+ version: 1.0.0.rc3
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-04-30 00:00:00.000000000 Z
12
+ date: 2013-05-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -102,7 +102,6 @@ files:
102
102
  - extra/foreman_startup.rb
103
103
  - extra/disk_facts.rb
104
104
  - config/initializers/discovery_setup.rb
105
- - config/environment.rb
106
105
  - config/routes.rb
107
106
  - lib/foreman_discovery.rb
108
107
  - lib/foreman_discovery/engine.rb
File without changes