foreman_discovery 1.0.0.rc2 → 1.0.0.rc3

Sign up to get free protection for your applications and to get access to all the features.
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