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 +15 -6
- data/app/controllers/discovers_controller.rb +80 -48
- data/app/helpers/discovers_helper.rb +5 -7
- data/app/models/host/discovered.rb +12 -2
- data/app/models/host/managed_extensions.rb +1 -1
- data/app/views/discovers/_discovers_list.html.erb +3 -1
- data/config/initializers/discovery_setup.rb +4 -6
- data/extra/build_iso.sh +73 -12
- data/extra/discover_host +40 -28
- data/lib/discovery_home_helper_patch.rb +1 -4
- data/lib/foreman_discovery/version.rb +1 -1
- data/lib/tasks.rake +8 -3
- metadata +2 -3
- data/config/environment.rb +0 -0
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
|
39
|
-
|
40
|
-
|
41
|
-
|
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
|
-
|
27
|
-
|
28
|
-
# filter graph time range
|
29
|
-
@range = nil
|
45
|
+
# filter graph time range
|
46
|
+
@range = nil
|
30
47
|
|
31
|
-
|
32
|
-
|
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
|
121
|
-
|
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
|
-
|
124
|
-
|
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
|
-
|
128
|
-
if
|
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
|
-
|
137
|
-
|
138
|
-
|
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'
|
30
|
-
actions.map do |action|
|
31
|
-
link_to(icon_text(action[2]), action[1], :title => action[0])
|
32
|
-
end.
|
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
|
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
|
-
|
15
|
-
|
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
|
-
|
32
|
-
|
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 "" >>
|
36
|
-
echo "sleep 20" >>
|
37
|
-
echo "/opt/foreman_startup.rb" >>
|
38
|
-
echo "/opt/discovery_init.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
|
-
|
42
|
-
chmod 755
|
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 "" >> ../
|
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
|
-
|
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
|
-
#
|
8
|
+
# For comparison
|
10
9
|
require 'rubygems'
|
11
|
-
require '
|
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
|
-
#
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
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
|
-
|
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
|
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']
|
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.
|
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-
|
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
|
data/config/environment.rb
DELETED
File without changes
|