cloud-mu 3.1.3 → 3.1.4
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.
- checksums.yaml +4 -4
- data/Dockerfile +10 -2
- data/bin/mu-adopt +5 -1
- data/bin/mu-load-config.rb +2 -3
- data/bin/mu-run-tests +112 -27
- data/cloud-mu.gemspec +20 -20
- data/cookbooks/mu-tools/libraries/helper.rb +2 -1
- data/cookbooks/mu-tools/libraries/monkey.rb +35 -0
- data/cookbooks/mu-tools/recipes/google_api.rb +2 -2
- data/cookbooks/mu-tools/resources/disk.rb +1 -1
- data/extras/image-generators/Google/centos6.yaml +1 -0
- data/extras/image-generators/Google/centos7.yaml +1 -1
- data/modules/mommacat.ru +5 -15
- data/modules/mu.rb +10 -14
- data/modules/mu/adoption.rb +20 -14
- data/modules/mu/cleanup.rb +13 -9
- data/modules/mu/cloud.rb +26 -26
- data/modules/mu/clouds/aws.rb +100 -59
- data/modules/mu/clouds/aws/alarm.rb +4 -2
- data/modules/mu/clouds/aws/bucket.rb +25 -21
- data/modules/mu/clouds/aws/cache_cluster.rb +25 -23
- data/modules/mu/clouds/aws/collection.rb +21 -20
- data/modules/mu/clouds/aws/container_cluster.rb +47 -26
- data/modules/mu/clouds/aws/database.rb +57 -68
- data/modules/mu/clouds/aws/dnszone.rb +14 -14
- data/modules/mu/clouds/aws/endpoint.rb +20 -16
- data/modules/mu/clouds/aws/firewall_rule.rb +19 -16
- data/modules/mu/clouds/aws/folder.rb +7 -7
- data/modules/mu/clouds/aws/function.rb +15 -12
- data/modules/mu/clouds/aws/group.rb +14 -10
- data/modules/mu/clouds/aws/habitat.rb +16 -13
- data/modules/mu/clouds/aws/loadbalancer.rb +16 -15
- data/modules/mu/clouds/aws/log.rb +13 -10
- data/modules/mu/clouds/aws/msg_queue.rb +15 -8
- data/modules/mu/clouds/aws/nosqldb.rb +18 -11
- data/modules/mu/clouds/aws/notifier.rb +11 -6
- data/modules/mu/clouds/aws/role.rb +87 -70
- data/modules/mu/clouds/aws/search_domain.rb +30 -19
- data/modules/mu/clouds/aws/server.rb +102 -72
- data/modules/mu/clouds/aws/server_pool.rb +47 -28
- data/modules/mu/clouds/aws/storage_pool.rb +5 -6
- data/modules/mu/clouds/aws/user.rb +13 -10
- data/modules/mu/clouds/aws/vpc.rb +135 -121
- data/modules/mu/clouds/azure.rb +16 -9
- data/modules/mu/clouds/azure/container_cluster.rb +2 -3
- data/modules/mu/clouds/azure/firewall_rule.rb +10 -10
- data/modules/mu/clouds/azure/habitat.rb +8 -6
- data/modules/mu/clouds/azure/loadbalancer.rb +5 -5
- data/modules/mu/clouds/azure/role.rb +8 -10
- data/modules/mu/clouds/azure/server.rb +65 -25
- data/modules/mu/clouds/azure/user.rb +5 -7
- data/modules/mu/clouds/azure/vpc.rb +12 -15
- data/modules/mu/clouds/cloudformation.rb +8 -7
- data/modules/mu/clouds/cloudformation/vpc.rb +2 -4
- data/modules/mu/clouds/google.rb +39 -24
- data/modules/mu/clouds/google/bucket.rb +9 -11
- data/modules/mu/clouds/google/container_cluster.rb +27 -42
- data/modules/mu/clouds/google/database.rb +6 -9
- data/modules/mu/clouds/google/firewall_rule.rb +11 -10
- data/modules/mu/clouds/google/folder.rb +16 -9
- data/modules/mu/clouds/google/function.rb +127 -161
- data/modules/mu/clouds/google/group.rb +21 -18
- data/modules/mu/clouds/google/habitat.rb +18 -15
- data/modules/mu/clouds/google/loadbalancer.rb +14 -16
- data/modules/mu/clouds/google/role.rb +48 -31
- data/modules/mu/clouds/google/server.rb +105 -105
- data/modules/mu/clouds/google/server_pool.rb +12 -31
- data/modules/mu/clouds/google/user.rb +67 -13
- data/modules/mu/clouds/google/vpc.rb +58 -65
- data/modules/mu/config.rb +89 -1738
- data/modules/mu/config/bucket.rb +3 -3
- data/modules/mu/config/collection.rb +3 -3
- data/modules/mu/config/container_cluster.rb +2 -2
- data/modules/mu/config/dnszone.rb +5 -5
- data/modules/mu/config/doc_helpers.rb +517 -0
- data/modules/mu/config/endpoint.rb +3 -3
- data/modules/mu/config/firewall_rule.rb +118 -3
- data/modules/mu/config/folder.rb +3 -3
- data/modules/mu/config/function.rb +2 -2
- data/modules/mu/config/group.rb +3 -3
- data/modules/mu/config/habitat.rb +3 -3
- data/modules/mu/config/loadbalancer.rb +3 -3
- data/modules/mu/config/log.rb +3 -3
- data/modules/mu/config/msg_queue.rb +3 -3
- data/modules/mu/config/nosqldb.rb +3 -3
- data/modules/mu/config/notifier.rb +2 -2
- data/modules/mu/config/ref.rb +333 -0
- data/modules/mu/config/role.rb +3 -3
- data/modules/mu/config/schema_helpers.rb +508 -0
- data/modules/mu/config/search_domain.rb +3 -3
- data/modules/mu/config/server.rb +86 -58
- data/modules/mu/config/server_pool.rb +2 -2
- data/modules/mu/config/tail.rb +189 -0
- data/modules/mu/config/user.rb +3 -3
- data/modules/mu/config/vpc.rb +44 -4
- data/modules/mu/defaults/Google.yaml +2 -2
- data/modules/mu/deploy.rb +13 -10
- data/modules/mu/groomer.rb +1 -1
- data/modules/mu/groomers/ansible.rb +69 -24
- data/modules/mu/groomers/chef.rb +52 -44
- data/modules/mu/logger.rb +17 -14
- data/modules/mu/master.rb +317 -2
- data/modules/mu/master/chef.rb +3 -4
- data/modules/mu/master/ldap.rb +3 -3
- data/modules/mu/master/ssl.rb +12 -2
- data/modules/mu/mommacat.rb +85 -1766
- data/modules/mu/mommacat/daemon.rb +394 -0
- data/modules/mu/mommacat/naming.rb +366 -0
- data/modules/mu/mommacat/storage.rb +689 -0
- data/modules/tests/bucket.yml +4 -0
- data/modules/tests/{win2k12.yaml → needwork/win2k12.yaml} +0 -0
- data/modules/tests/regrooms/aws-iam.yaml +201 -0
- data/modules/tests/regrooms/bucket.yml +19 -0
- metadata +112 -102
data/modules/mu/logger.rb
CHANGED
|
@@ -66,13 +66,16 @@ module MU
|
|
|
66
66
|
def log(msg,
|
|
67
67
|
level=INFO,
|
|
68
68
|
details: nil,
|
|
69
|
-
html:
|
|
70
|
-
verbosity:
|
|
71
|
-
handle:
|
|
72
|
-
color:
|
|
69
|
+
html: nil,
|
|
70
|
+
verbosity: nil,
|
|
71
|
+
handle: nil,
|
|
72
|
+
color: nil,
|
|
73
73
|
deploy: MU.mommacat
|
|
74
74
|
)
|
|
75
75
|
verbosity ||= @verbosity
|
|
76
|
+
html ||= @html
|
|
77
|
+
handle ||= @handle
|
|
78
|
+
color ||= @color
|
|
76
79
|
return if verbosity == MU::Logger::SILENT
|
|
77
80
|
return if verbosity < MU::Logger::LOUD and level == DEBUG
|
|
78
81
|
return if verbosity < MU::Logger::NORMAL and level == INFO
|
|
@@ -101,7 +104,7 @@ module MU
|
|
|
101
104
|
end
|
|
102
105
|
details = PP.pp(details, '') if !details.is_a?(String)
|
|
103
106
|
end
|
|
104
|
-
details = "<pre>"+details+"</pre>" if
|
|
107
|
+
details = "<pre>"+details+"</pre>" if html
|
|
105
108
|
# We get passed literal quoted newlines sometimes, fix 'em. Get Windows'
|
|
106
109
|
# ugly line feeds too.
|
|
107
110
|
if !details.nil?
|
|
@@ -139,7 +142,7 @@ module MU
|
|
|
139
142
|
@summary << msg
|
|
140
143
|
when DEBUG
|
|
141
144
|
if verbosity >= MU::Logger::LOUD
|
|
142
|
-
if
|
|
145
|
+
if html
|
|
143
146
|
html_out "#{time} - #{caller_name} - #{msg}", "orange"
|
|
144
147
|
html_out " #{details}" if details
|
|
145
148
|
elsif color
|
|
@@ -154,7 +157,7 @@ module MU
|
|
|
154
157
|
end
|
|
155
158
|
when INFO
|
|
156
159
|
if verbosity >= MU::Logger::NORMAL
|
|
157
|
-
if
|
|
160
|
+
if html
|
|
158
161
|
html_out "#{time} - #{caller_name} - #{msg}", "green"
|
|
159
162
|
elsif color
|
|
160
163
|
msgs << "#{time} - #{caller_name} - #{msg}".green.on_black
|
|
@@ -162,7 +165,7 @@ module MU
|
|
|
162
165
|
msgs << "#{time} - #{caller_name} - #{msg}"
|
|
163
166
|
end
|
|
164
167
|
if verbosity >= MU::Logger::LOUD
|
|
165
|
-
if
|
|
168
|
+
if html
|
|
166
169
|
html_out " #{details}"
|
|
167
170
|
elsif color
|
|
168
171
|
msgs << "#{details}".white.on_black if details
|
|
@@ -174,7 +177,7 @@ module MU
|
|
|
174
177
|
Syslog.log(Syslog::LOG_NOTICE, details.gsub(/%/, '')) if details
|
|
175
178
|
end
|
|
176
179
|
when NOTICE
|
|
177
|
-
if
|
|
180
|
+
if html
|
|
178
181
|
html_out "#{time} - #{caller_name} - #{msg}", "yellow"
|
|
179
182
|
elsif color
|
|
180
183
|
msgs << "#{time} - #{caller_name} - #{msg}".yellow.on_black
|
|
@@ -182,7 +185,7 @@ module MU
|
|
|
182
185
|
msgs << "#{time} - #{caller_name} - #{msg}"
|
|
183
186
|
end
|
|
184
187
|
if verbosity >= MU::Logger::QUIET
|
|
185
|
-
if
|
|
188
|
+
if html
|
|
186
189
|
html_out "#{caller_name} - #{msg}"
|
|
187
190
|
elsif color
|
|
188
191
|
msgs << "#{details}".white.on_black if details
|
|
@@ -193,7 +196,7 @@ module MU
|
|
|
193
196
|
Syslog.log(Syslog::LOG_NOTICE, msg.gsub(/%/, ''))
|
|
194
197
|
Syslog.log(Syslog::LOG_NOTICE, details.gsub(/%/, '')) if details
|
|
195
198
|
when WARN
|
|
196
|
-
if
|
|
199
|
+
if html
|
|
197
200
|
html_out "#{time} - #{caller_name} - #{msg}", "orange"
|
|
198
201
|
elsif color
|
|
199
202
|
msgs << "#{time} - #{caller_name} - #{msg}".light_red.on_black
|
|
@@ -201,7 +204,7 @@ module MU
|
|
|
201
204
|
msgs << "#{time} - #{caller_name} - #{msg}"
|
|
202
205
|
end
|
|
203
206
|
if verbosity >= MU::Logger::SILENT
|
|
204
|
-
if
|
|
207
|
+
if html
|
|
205
208
|
html_out "#{caller_name} - #{msg}"
|
|
206
209
|
elsif color
|
|
207
210
|
msgs << "#{details}".white.on_black if details
|
|
@@ -212,7 +215,7 @@ module MU
|
|
|
212
215
|
Syslog.log(Syslog::LOG_WARNING, msg.gsub(/%/, ''))
|
|
213
216
|
Syslog.log(Syslog::LOG_WARNING, details.gsub(/%/, '')) if details
|
|
214
217
|
when ERR
|
|
215
|
-
if
|
|
218
|
+
if html
|
|
216
219
|
html_out "#{time} - #{caller_name} - #{msg}", "red"
|
|
217
220
|
html_out " #{details}" if details
|
|
218
221
|
elsif color
|
|
@@ -225,7 +228,7 @@ module MU
|
|
|
225
228
|
Syslog.log(Syslog::LOG_ERR, msg.gsub(/%/, ''))
|
|
226
229
|
Syslog.log(Syslog::LOG_ERR, details.gsub(/%/, '')) if details
|
|
227
230
|
else
|
|
228
|
-
if
|
|
231
|
+
if html
|
|
229
232
|
html_out "#{time} - #{caller_name} - #{msg}"
|
|
230
233
|
html_out " #{details}" if details
|
|
231
234
|
elsif color
|
data/modules/mu/master.rb
CHANGED
|
@@ -24,6 +24,12 @@ module MU
|
|
|
24
24
|
autoload :LDAP, 'mu/master/ldap'
|
|
25
25
|
autoload :SSL, 'mu/master/ssl'
|
|
26
26
|
|
|
27
|
+
# Home directory of the invoking user
|
|
28
|
+
MY_HOME = Etc.getpwuid(Process.uid).dir
|
|
29
|
+
|
|
30
|
+
# Home directory of the Nagios user, if we're in a non-gem context
|
|
31
|
+
NAGIOS_HOME = "/opt/mu/var/nagios_user_home" # XXX gross
|
|
32
|
+
|
|
27
33
|
# @param users [Hash]: User metadata of the type returned by listUsers
|
|
28
34
|
def self.printUsersToTerminal(users = MU::Master.listUsers)
|
|
29
35
|
labeled = false
|
|
@@ -228,7 +234,7 @@ module MU
|
|
|
228
234
|
begin
|
|
229
235
|
resp = MU::Cloud::AWS.s3.get_object(bucket: MU.adminBucketName, key: cryptfile)
|
|
230
236
|
body = resp.body
|
|
231
|
-
rescue
|
|
237
|
+
rescue StandardError => e
|
|
232
238
|
MU.log "Failed to fetch #{cryptfile} from S3 bucket #{MU.adminBucketName}", MU::ERR, details: e.inspect
|
|
233
239
|
%x{/bin/dd if=/dev/urandom of=#{temp_dev} bs=1M count=1 > /dev/null 2>&1}
|
|
234
240
|
raise e
|
|
@@ -236,7 +242,7 @@ module MU
|
|
|
236
242
|
elsif MU::Cloud::Google.hosted?
|
|
237
243
|
begin
|
|
238
244
|
body = MU::Cloud::Google.storage.get_object(MU.adminBucketName, cryptfile)
|
|
239
|
-
rescue
|
|
245
|
+
rescue StandardError => e
|
|
240
246
|
MU.log "Failed to fetch #{cryptfile} from Cloud Storage bucket #{MU.adminBucketName}", MU::ERR, details: e.inspect
|
|
241
247
|
%x{/bin/dd if=/dev/urandom of=#{temp_dev} bs=1M count=1 > /dev/null 2>&1}
|
|
242
248
|
raise e
|
|
@@ -493,5 +499,314 @@ module MU
|
|
|
493
499
|
end
|
|
494
500
|
end
|
|
495
501
|
|
|
502
|
+
# Clean a node's entries out of /etc/hosts
|
|
503
|
+
# @param node [String]: The node's name
|
|
504
|
+
# @return [void]
|
|
505
|
+
def self.removeInstanceFromEtcHosts(node)
|
|
506
|
+
return if MU.mu_user != "mu"
|
|
507
|
+
hostsfile = "/etc/hosts"
|
|
508
|
+
FileUtils.copy(hostsfile, "#{hostsfile}.bak-#{MU.deploy_id}")
|
|
509
|
+
File.open(hostsfile, File::CREAT|File::RDWR, 0644) { |f|
|
|
510
|
+
f.flock(File::LOCK_EX)
|
|
511
|
+
newlines = Array.new
|
|
512
|
+
f.readlines.each { |line|
|
|
513
|
+
newlines << line if !line.match(/ #{node}(\s|$)/)
|
|
514
|
+
}
|
|
515
|
+
f.rewind
|
|
516
|
+
f.truncate(0)
|
|
517
|
+
f.puts(newlines)
|
|
518
|
+
f.flush
|
|
519
|
+
|
|
520
|
+
f.flock(File::LOCK_UN)
|
|
521
|
+
}
|
|
522
|
+
end
|
|
523
|
+
|
|
524
|
+
|
|
525
|
+
# Insert node names associated with a new instance into /etc/hosts so we
|
|
526
|
+
# can treat them as if they were real DNS entries. Especially helpful when
|
|
527
|
+
# Chef/Ohai mistake the proper hostname, e.g. when bootstrapping Windows.
|
|
528
|
+
# @param public_ip [String]: The node's IP address
|
|
529
|
+
# @param chef_name [String]: The node's Chef node name
|
|
530
|
+
# @param system_name [String]: The node's local system name
|
|
531
|
+
# @return [void]
|
|
532
|
+
def self.addInstanceToEtcHosts(public_ip, chef_name = nil, system_name = nil)
|
|
533
|
+
|
|
534
|
+
# XXX cover ipv6 case
|
|
535
|
+
if public_ip.nil? or !public_ip.match(/^\d+\.\d+\.\d+\.\d+$/) or (chef_name.nil? and system_name.nil?)
|
|
536
|
+
raise MuError, "addInstanceToEtcHosts requires public_ip and one or both of chef_name and system_name!"
|
|
537
|
+
end
|
|
538
|
+
if chef_name == "localhost" or system_name == "localhost"
|
|
539
|
+
raise MuError, "Can't set localhost as a name in addInstanceToEtcHosts"
|
|
540
|
+
end
|
|
541
|
+
|
|
542
|
+
if !["mu", "root"].include?(MU.mu_user)
|
|
543
|
+
response = nil
|
|
544
|
+
begin
|
|
545
|
+
response = open("https://127.0.0.1:#{MU.mommaCatPort.to_s}/rest/hosts_add/#{chef_name}/#{public_ip}").read
|
|
546
|
+
rescue Errno::ECONNRESET, Errno::ECONNREFUSED
|
|
547
|
+
end
|
|
548
|
+
if response != "ok"
|
|
549
|
+
MU.log "Error adding #{public_ip} to /etc/hosts via MommaCat request", MU::ERR
|
|
550
|
+
end
|
|
551
|
+
return
|
|
552
|
+
end
|
|
553
|
+
|
|
554
|
+
File.readlines("/etc/hosts").each { |line|
|
|
555
|
+
if line.match(/^#{public_ip} /) or (chef_name != nil and line.match(/ #{chef_name}(\s|$)/)) or (system_name != nil and line.match(/ #{system_name}(\s|$)/))
|
|
556
|
+
MU.log "Ignoring attempt to add duplicate /etc/hosts entry: #{public_ip} #{chef_name} #{system_name}", MU::DEBUG
|
|
557
|
+
return
|
|
558
|
+
end
|
|
559
|
+
}
|
|
560
|
+
File.open("/etc/hosts", 'a') { |etc_hosts|
|
|
561
|
+
etc_hosts.flock(File::LOCK_EX)
|
|
562
|
+
etc_hosts.puts("#{public_ip} #{chef_name} #{system_name}")
|
|
563
|
+
etc_hosts.flock(File::LOCK_UN)
|
|
564
|
+
}
|
|
565
|
+
MU.log("Added to /etc/hosts: #{public_ip} #{chef_name} #{system_name}")
|
|
566
|
+
end
|
|
567
|
+
|
|
568
|
+
@ssh_semaphore = Mutex.new
|
|
569
|
+
# Insert a definition for a node into our SSH config.
|
|
570
|
+
# @param server [MU::Cloud::Server]: The name of the node.
|
|
571
|
+
# @param names [Array<String>]: Other names that we'd like this host to be known by for SSH purposes
|
|
572
|
+
# @param ssh_dir [String]: The configuration directory of the SSH config to emit.
|
|
573
|
+
# @param ssh_conf [String]: A specific SSH configuration file to write entries into.
|
|
574
|
+
# @param ssh_owner [String]: The preferred owner of the SSH configuration files.
|
|
575
|
+
# @param timeout [Integer]: An alternate timeout value for connections to this server.
|
|
576
|
+
# @return [void]
|
|
577
|
+
def self.addHostToSSHConfig(server,
|
|
578
|
+
ssh_dir: "#{Etc.getpwuid(Process.uid).dir}/.ssh",
|
|
579
|
+
ssh_conf: "#{Etc.getpwuid(Process.uid).dir}/.ssh/config",
|
|
580
|
+
ssh_owner: Etc.getpwuid(Process.uid).name,
|
|
581
|
+
names: [],
|
|
582
|
+
timeout: 0
|
|
583
|
+
)
|
|
584
|
+
if server.nil?
|
|
585
|
+
MU.log "Called addHostToSSHConfig without a MU::Cloud::Server object", MU::ERR, details: caller
|
|
586
|
+
return nil
|
|
587
|
+
end
|
|
588
|
+
|
|
589
|
+
_nat_ssh_key, nat_ssh_user, nat_ssh_host, canonical_ip, ssh_user, ssh_key_name = begin
|
|
590
|
+
server.getSSHConfig
|
|
591
|
+
rescue MU::MuError
|
|
592
|
+
return
|
|
593
|
+
end
|
|
594
|
+
|
|
595
|
+
if ssh_user.nil? or ssh_user.empty?
|
|
596
|
+
MU.log "Failed to extract ssh_user for #{server.mu_name} addHostToSSHConfig", MU::ERR
|
|
597
|
+
return
|
|
598
|
+
end
|
|
599
|
+
if canonical_ip.nil? or canonical_ip.empty?
|
|
600
|
+
MU.log "Failed to extract canonical_ip for #{server.mu_name} addHostToSSHConfig", MU::ERR
|
|
601
|
+
return
|
|
602
|
+
end
|
|
603
|
+
if ssh_key_name.nil? or ssh_key_name.empty?
|
|
604
|
+
MU.log "Failed to extract ssh_key_name for #{ssh_key_name.mu_name} in addHostToSSHConfig", MU::ERR
|
|
605
|
+
return
|
|
606
|
+
end
|
|
607
|
+
|
|
608
|
+
@ssh_semaphore.synchronize {
|
|
609
|
+
|
|
610
|
+
if File.exist?(ssh_conf)
|
|
611
|
+
File.readlines(ssh_conf).each { |line|
|
|
612
|
+
if line.match(/^Host #{server.mu_name} /)
|
|
613
|
+
MU.log("Attempt to add duplicate #{ssh_conf} entry for #{server.mu_name}", MU::WARN)
|
|
614
|
+
return
|
|
615
|
+
end
|
|
616
|
+
}
|
|
617
|
+
end
|
|
618
|
+
|
|
619
|
+
File.open(ssh_conf, 'a', 0600) { |ssh_config|
|
|
620
|
+
ssh_config.flock(File::LOCK_EX)
|
|
621
|
+
host_str = "Host #{server.mu_name} #{server.canonicalIP}"
|
|
622
|
+
if !names.nil? and names.size > 0
|
|
623
|
+
host_str = host_str+" "+names.join(" ")
|
|
624
|
+
end
|
|
625
|
+
ssh_config.puts host_str
|
|
626
|
+
ssh_config.puts " Hostname #{server.canonicalIP}"
|
|
627
|
+
if !nat_ssh_host.nil? and server.canonicalIP != nat_ssh_host
|
|
628
|
+
ssh_config.puts " ProxyCommand ssh -W %h:%p #{nat_ssh_user}@#{nat_ssh_host}"
|
|
629
|
+
end
|
|
630
|
+
if timeout > 0
|
|
631
|
+
ssh_config.puts " ConnectTimeout #{timeout}"
|
|
632
|
+
end
|
|
633
|
+
|
|
634
|
+
ssh_config.puts " User #{ssh_user}"
|
|
635
|
+
# XXX I'd rather add the host key to known_hosts, but Net::SSH is a little dumb
|
|
636
|
+
ssh_config.puts " StrictHostKeyChecking no"
|
|
637
|
+
ssh_config.puts " ServerAliveInterval 60"
|
|
638
|
+
|
|
639
|
+
ssh_config.puts " IdentityFile #{ssh_dir}/#{ssh_key_name}"
|
|
640
|
+
if !File.exist?("#{ssh_dir}/#{ssh_key_name}")
|
|
641
|
+
MU.log "#{server.mu_name} - ssh private key #{ssh_dir}/#{ssh_key_name} does not exist", MU::WARN
|
|
642
|
+
end
|
|
643
|
+
|
|
644
|
+
ssh_config.flock(File::LOCK_UN)
|
|
645
|
+
ssh_config.chown(Etc.getpwnam(ssh_owner).uid, Etc.getpwnam(ssh_owner).gid)
|
|
646
|
+
}
|
|
647
|
+
MU.log "Wrote #{server.mu_name} ssh key to #{ssh_dir}/config", MU::DEBUG
|
|
648
|
+
return "#{ssh_dir}/#{ssh_key_name}"
|
|
649
|
+
}
|
|
650
|
+
end
|
|
651
|
+
|
|
652
|
+
# Clean an IP address out of ~/.ssh/known hosts
|
|
653
|
+
# @param ip [String]: The IP to remove
|
|
654
|
+
# @return [void]
|
|
655
|
+
def self.removeIPFromSSHKnownHosts(ip, noop: false)
|
|
656
|
+
return if ip.nil?
|
|
657
|
+
sshdir = "#{MY_HOME}/.ssh"
|
|
658
|
+
knownhosts = "#{sshdir}/known_hosts"
|
|
659
|
+
|
|
660
|
+
if File.exist?(knownhosts) and File.open(knownhosts).read.match(/^#{Regexp.quote(ip)} /)
|
|
661
|
+
MU.log "Expunging old #{ip} entry from #{knownhosts}", MU::NOTICE
|
|
662
|
+
if !noop
|
|
663
|
+
File.open(knownhosts, File::CREAT|File::RDWR, 0600) { |f|
|
|
664
|
+
f.flock(File::LOCK_EX)
|
|
665
|
+
newlines = Array.new
|
|
666
|
+
f.readlines.each { |line|
|
|
667
|
+
next if line.match(/^#{Regexp.quote(ip)} /)
|
|
668
|
+
newlines << line
|
|
669
|
+
}
|
|
670
|
+
f.rewind
|
|
671
|
+
f.truncate(0)
|
|
672
|
+
f.puts(newlines)
|
|
673
|
+
f.flush
|
|
674
|
+
f.flock(File::LOCK_UN)
|
|
675
|
+
}
|
|
676
|
+
end
|
|
677
|
+
end
|
|
678
|
+
end
|
|
679
|
+
|
|
680
|
+
# Clean a node's entries out of ~/.ssh/config
|
|
681
|
+
# @param nodename [String]: The node's name
|
|
682
|
+
# @return [void]
|
|
683
|
+
def self.removeHostFromSSHConfig(nodename, noop: false)
|
|
684
|
+
sshdir = "#{MY_HOME}/.ssh"
|
|
685
|
+
sshconf = "#{sshdir}/config"
|
|
686
|
+
|
|
687
|
+
if File.exist?(sshconf) and File.open(sshconf).read.match(/ #{nodename} /)
|
|
688
|
+
MU.log "Expunging old #{nodename} entry from #{sshconf}", MU::DEBUG
|
|
689
|
+
if !noop
|
|
690
|
+
File.open(sshconf, File::CREAT|File::RDWR, 0600) { |f|
|
|
691
|
+
f.flock(File::LOCK_EX)
|
|
692
|
+
newlines = Array.new
|
|
693
|
+
delete_block = false
|
|
694
|
+
f.readlines.each { |line|
|
|
695
|
+
if line.match(/^Host #{nodename}(\s|$)/)
|
|
696
|
+
delete_block = true
|
|
697
|
+
elsif line.match(/^Host /)
|
|
698
|
+
delete_block = false
|
|
699
|
+
end
|
|
700
|
+
newlines << line if !delete_block
|
|
701
|
+
}
|
|
702
|
+
f.rewind
|
|
703
|
+
f.truncate(0)
|
|
704
|
+
f.puts(newlines)
|
|
705
|
+
f.flush
|
|
706
|
+
f.flock(File::LOCK_UN)
|
|
707
|
+
}
|
|
708
|
+
end
|
|
709
|
+
end
|
|
710
|
+
end
|
|
711
|
+
|
|
712
|
+
# Ensure that the Nagios configuration local to the MU master has been
|
|
713
|
+
# updated, and make sure Nagios has all of the ssh keys it needs to tunnel
|
|
714
|
+
# to client nodes.
|
|
715
|
+
# @return [void]
|
|
716
|
+
def self.syncMonitoringConfig(blocking = true)
|
|
717
|
+
return if Etc.getpwuid(Process.uid).name != "root" or (MU.mu_user != "mu" and MU.mu_user != "root")
|
|
718
|
+
parent_thread_id = Thread.current.object_id
|
|
719
|
+
nagios_threads = []
|
|
720
|
+
nagios_threads << Thread.new {
|
|
721
|
+
MU.dupGlobals(parent_thread_id)
|
|
722
|
+
realhome = Etc.getpwnam("nagios").dir
|
|
723
|
+
[NAGIOS_HOME, "#{NAGIOS_HOME}/.ssh"].each { |dir|
|
|
724
|
+
Dir.mkdir(dir, 0711) if !Dir.exist?(dir)
|
|
725
|
+
File.chown(Etc.getpwnam("nagios").uid, Etc.getpwnam("nagios").gid, dir)
|
|
726
|
+
}
|
|
727
|
+
if realhome != NAGIOS_HOME and Dir.exist?(realhome) and !File.symlink?("#{realhome}/.ssh")
|
|
728
|
+
File.rename("#{realhome}/.ssh", "#{realhome}/.ssh.#{$$}") if Dir.exist?("#{realhome}/.ssh")
|
|
729
|
+
File.symlink("#{NAGIOS_HOME}/.ssh", Etc.getpwnam("nagios").dir+"/.ssh")
|
|
730
|
+
end
|
|
731
|
+
MU.log "Updating #{NAGIOS_HOME}/.ssh/config..."
|
|
732
|
+
ssh_lock = File.new("#{NAGIOS_HOME}/.ssh/config.mu.lock", File::CREAT|File::TRUNC|File::RDWR, 0600)
|
|
733
|
+
ssh_lock.flock(File::LOCK_EX)
|
|
734
|
+
ssh_conf = File.new("#{NAGIOS_HOME}/.ssh/config.tmp", File::CREAT|File::TRUNC|File::RDWR, 0600)
|
|
735
|
+
ssh_conf.puts "Host MU-MASTER localhost"
|
|
736
|
+
ssh_conf.puts " Hostname localhost"
|
|
737
|
+
ssh_conf.puts " User root"
|
|
738
|
+
ssh_conf.puts " IdentityFile #{NAGIOS_HOME}/.ssh/id_rsa"
|
|
739
|
+
ssh_conf.puts " StrictHostKeyChecking no"
|
|
740
|
+
ssh_conf.close
|
|
741
|
+
FileUtils.cp("#{@myhome}/.ssh/id_rsa", "#{NAGIOS_HOME}/.ssh/id_rsa")
|
|
742
|
+
File.chown(Etc.getpwnam("nagios").uid, Etc.getpwnam("nagios").gid, "#{NAGIOS_HOME}/.ssh/id_rsa")
|
|
743
|
+
threads = []
|
|
744
|
+
|
|
745
|
+
parent_thread_id = Thread.current.object_id
|
|
746
|
+
MU::MommaCat.listDeploys.sort.each { |deploy_id|
|
|
747
|
+
begin
|
|
748
|
+
# We don't want to use cached litter information here because this is also called by cleanTerminatedInstances.
|
|
749
|
+
deploy = MU::MommaCat.getLitter(deploy_id)
|
|
750
|
+
if deploy.ssh_key_name.nil? or deploy.ssh_key_name.empty?
|
|
751
|
+
MU.log "Failed to extract ssh key name from #{deploy_id} in syncMonitoringConfig", MU::ERR if deploy.kittens.has_key?("servers")
|
|
752
|
+
next
|
|
753
|
+
end
|
|
754
|
+
FileUtils.cp("#{@myhome}/.ssh/#{deploy.ssh_key_name}", "#{NAGIOS_HOME}/.ssh/#{deploy.ssh_key_name}")
|
|
755
|
+
File.chown(Etc.getpwnam("nagios").uid, Etc.getpwnam("nagios").gid, "#{NAGIOS_HOME}/.ssh/#{deploy.ssh_key_name}")
|
|
756
|
+
if deploy.kittens.has_key?("servers")
|
|
757
|
+
deploy.kittens["servers"].values.each { |nodeclasses|
|
|
758
|
+
nodeclasses.values.each { |nodes|
|
|
759
|
+
nodes.values.each { |server|
|
|
760
|
+
next if !server.cloud_desc
|
|
761
|
+
MU.dupGlobals(parent_thread_id)
|
|
762
|
+
threads << Thread.new {
|
|
763
|
+
MU::MommaCat.setThreadContext(deploy)
|
|
764
|
+
MU.log "Adding #{server.mu_name} to #{NAGIOS_HOME}/.ssh/config", MU::DEBUG
|
|
765
|
+
MU::Master.addHostToSSHConfig(
|
|
766
|
+
server,
|
|
767
|
+
ssh_dir: "#{NAGIOS_HOME}/.ssh",
|
|
768
|
+
ssh_conf: "#{NAGIOS_HOME}/.ssh/config.tmp",
|
|
769
|
+
ssh_owner: "nagios"
|
|
770
|
+
)
|
|
771
|
+
MU.purgeGlobals
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
end
|
|
777
|
+
rescue StandardError => e
|
|
778
|
+
MU.log "#{e.inspect} while generating Nagios SSH config in #{deploy_id}", MU::ERR, details: e.backtrace
|
|
779
|
+
end
|
|
780
|
+
}
|
|
781
|
+
threads.each { |t|
|
|
782
|
+
t.join
|
|
783
|
+
}
|
|
784
|
+
ssh_lock.flock(File::LOCK_UN)
|
|
785
|
+
ssh_lock.close
|
|
786
|
+
File.chown(Etc.getpwnam("nagios").uid, Etc.getpwnam("nagios").gid, "#{NAGIOS_HOME}/.ssh/config.tmp")
|
|
787
|
+
File.rename("#{NAGIOS_HOME}/.ssh/config.tmp", "#{NAGIOS_HOME}/.ssh/config")
|
|
788
|
+
|
|
789
|
+
MU.log "Updating Nagios monitoring config, this may take a while..."
|
|
790
|
+
output = nil
|
|
791
|
+
if $MU_CFG and !$MU_CFG['master_runlist_extras'].nil?
|
|
792
|
+
output = %x{#{MU::Groomer::Chef.chefclient} -o 'role[mu-master-nagios-only],#{$MU_CFG['master_runlist_extras'].join(",")}' 2>&1}
|
|
793
|
+
else
|
|
794
|
+
output = %x{#{MU::Groomer::Chef.chefclient} -o 'role[mu-master-nagios-only]' 2>&1}
|
|
795
|
+
end
|
|
796
|
+
|
|
797
|
+
if $?.exitstatus != 0
|
|
798
|
+
MU.log "Nagios monitoring config update returned a non-zero exit code!", MU::ERR, details: output
|
|
799
|
+
else
|
|
800
|
+
MU.log "Nagios monitoring config update complete."
|
|
801
|
+
end
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
if blocking
|
|
805
|
+
nagios_threads.each { |t|
|
|
806
|
+
t.join
|
|
807
|
+
}
|
|
808
|
+
end
|
|
809
|
+
end
|
|
810
|
+
|
|
496
811
|
end
|
|
497
812
|
end
|
data/modules/mu/master/chef.rb
CHANGED
|
@@ -48,7 +48,7 @@ module MU
|
|
|
48
48
|
def self.deleteOrg(org)
|
|
49
49
|
begin
|
|
50
50
|
Timeout::timeout(45) {
|
|
51
|
-
|
|
51
|
+
chefAPI.delete("organizations/#{org}")
|
|
52
52
|
}
|
|
53
53
|
MU.log "Removed Chef organization #{org}", MU::NOTICE
|
|
54
54
|
return true
|
|
@@ -82,7 +82,7 @@ module MU
|
|
|
82
82
|
|
|
83
83
|
begin
|
|
84
84
|
Timeout::timeout(45) {
|
|
85
|
-
|
|
85
|
+
chefAPI.delete("users/#{chef_user}")
|
|
86
86
|
}
|
|
87
87
|
MU.log "Removed Chef user #{chef_user}", MU::NOTICE
|
|
88
88
|
return true
|
|
@@ -200,7 +200,6 @@ module MU
|
|
|
200
200
|
|
|
201
201
|
# This organization does not yet exist, create it
|
|
202
202
|
if !existing_org
|
|
203
|
-
name = org.dup if fullname.nil?
|
|
204
203
|
begin
|
|
205
204
|
org_data = {
|
|
206
205
|
:name => org.dup,
|
|
@@ -255,7 +254,7 @@ module MU
|
|
|
255
254
|
}
|
|
256
255
|
remove_users.each { |user|
|
|
257
256
|
begin
|
|
258
|
-
|
|
257
|
+
chefAPI.delete("organizations/#{org}/users/#{user}")
|
|
259
258
|
MU.log "Removed Chef user #{user} from organization #{org}", MU::NOTICE
|
|
260
259
|
rescue Net::HTTPServerException => e
|
|
261
260
|
end
|