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 +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
|