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.
Files changed (114) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +10 -2
  3. data/bin/mu-adopt +5 -1
  4. data/bin/mu-load-config.rb +2 -3
  5. data/bin/mu-run-tests +112 -27
  6. data/cloud-mu.gemspec +20 -20
  7. data/cookbooks/mu-tools/libraries/helper.rb +2 -1
  8. data/cookbooks/mu-tools/libraries/monkey.rb +35 -0
  9. data/cookbooks/mu-tools/recipes/google_api.rb +2 -2
  10. data/cookbooks/mu-tools/resources/disk.rb +1 -1
  11. data/extras/image-generators/Google/centos6.yaml +1 -0
  12. data/extras/image-generators/Google/centos7.yaml +1 -1
  13. data/modules/mommacat.ru +5 -15
  14. data/modules/mu.rb +10 -14
  15. data/modules/mu/adoption.rb +20 -14
  16. data/modules/mu/cleanup.rb +13 -9
  17. data/modules/mu/cloud.rb +26 -26
  18. data/modules/mu/clouds/aws.rb +100 -59
  19. data/modules/mu/clouds/aws/alarm.rb +4 -2
  20. data/modules/mu/clouds/aws/bucket.rb +25 -21
  21. data/modules/mu/clouds/aws/cache_cluster.rb +25 -23
  22. data/modules/mu/clouds/aws/collection.rb +21 -20
  23. data/modules/mu/clouds/aws/container_cluster.rb +47 -26
  24. data/modules/mu/clouds/aws/database.rb +57 -68
  25. data/modules/mu/clouds/aws/dnszone.rb +14 -14
  26. data/modules/mu/clouds/aws/endpoint.rb +20 -16
  27. data/modules/mu/clouds/aws/firewall_rule.rb +19 -16
  28. data/modules/mu/clouds/aws/folder.rb +7 -7
  29. data/modules/mu/clouds/aws/function.rb +15 -12
  30. data/modules/mu/clouds/aws/group.rb +14 -10
  31. data/modules/mu/clouds/aws/habitat.rb +16 -13
  32. data/modules/mu/clouds/aws/loadbalancer.rb +16 -15
  33. data/modules/mu/clouds/aws/log.rb +13 -10
  34. data/modules/mu/clouds/aws/msg_queue.rb +15 -8
  35. data/modules/mu/clouds/aws/nosqldb.rb +18 -11
  36. data/modules/mu/clouds/aws/notifier.rb +11 -6
  37. data/modules/mu/clouds/aws/role.rb +87 -70
  38. data/modules/mu/clouds/aws/search_domain.rb +30 -19
  39. data/modules/mu/clouds/aws/server.rb +102 -72
  40. data/modules/mu/clouds/aws/server_pool.rb +47 -28
  41. data/modules/mu/clouds/aws/storage_pool.rb +5 -6
  42. data/modules/mu/clouds/aws/user.rb +13 -10
  43. data/modules/mu/clouds/aws/vpc.rb +135 -121
  44. data/modules/mu/clouds/azure.rb +16 -9
  45. data/modules/mu/clouds/azure/container_cluster.rb +2 -3
  46. data/modules/mu/clouds/azure/firewall_rule.rb +10 -10
  47. data/modules/mu/clouds/azure/habitat.rb +8 -6
  48. data/modules/mu/clouds/azure/loadbalancer.rb +5 -5
  49. data/modules/mu/clouds/azure/role.rb +8 -10
  50. data/modules/mu/clouds/azure/server.rb +65 -25
  51. data/modules/mu/clouds/azure/user.rb +5 -7
  52. data/modules/mu/clouds/azure/vpc.rb +12 -15
  53. data/modules/mu/clouds/cloudformation.rb +8 -7
  54. data/modules/mu/clouds/cloudformation/vpc.rb +2 -4
  55. data/modules/mu/clouds/google.rb +39 -24
  56. data/modules/mu/clouds/google/bucket.rb +9 -11
  57. data/modules/mu/clouds/google/container_cluster.rb +27 -42
  58. data/modules/mu/clouds/google/database.rb +6 -9
  59. data/modules/mu/clouds/google/firewall_rule.rb +11 -10
  60. data/modules/mu/clouds/google/folder.rb +16 -9
  61. data/modules/mu/clouds/google/function.rb +127 -161
  62. data/modules/mu/clouds/google/group.rb +21 -18
  63. data/modules/mu/clouds/google/habitat.rb +18 -15
  64. data/modules/mu/clouds/google/loadbalancer.rb +14 -16
  65. data/modules/mu/clouds/google/role.rb +48 -31
  66. data/modules/mu/clouds/google/server.rb +105 -105
  67. data/modules/mu/clouds/google/server_pool.rb +12 -31
  68. data/modules/mu/clouds/google/user.rb +67 -13
  69. data/modules/mu/clouds/google/vpc.rb +58 -65
  70. data/modules/mu/config.rb +89 -1738
  71. data/modules/mu/config/bucket.rb +3 -3
  72. data/modules/mu/config/collection.rb +3 -3
  73. data/modules/mu/config/container_cluster.rb +2 -2
  74. data/modules/mu/config/dnszone.rb +5 -5
  75. data/modules/mu/config/doc_helpers.rb +517 -0
  76. data/modules/mu/config/endpoint.rb +3 -3
  77. data/modules/mu/config/firewall_rule.rb +118 -3
  78. data/modules/mu/config/folder.rb +3 -3
  79. data/modules/mu/config/function.rb +2 -2
  80. data/modules/mu/config/group.rb +3 -3
  81. data/modules/mu/config/habitat.rb +3 -3
  82. data/modules/mu/config/loadbalancer.rb +3 -3
  83. data/modules/mu/config/log.rb +3 -3
  84. data/modules/mu/config/msg_queue.rb +3 -3
  85. data/modules/mu/config/nosqldb.rb +3 -3
  86. data/modules/mu/config/notifier.rb +2 -2
  87. data/modules/mu/config/ref.rb +333 -0
  88. data/modules/mu/config/role.rb +3 -3
  89. data/modules/mu/config/schema_helpers.rb +508 -0
  90. data/modules/mu/config/search_domain.rb +3 -3
  91. data/modules/mu/config/server.rb +86 -58
  92. data/modules/mu/config/server_pool.rb +2 -2
  93. data/modules/mu/config/tail.rb +189 -0
  94. data/modules/mu/config/user.rb +3 -3
  95. data/modules/mu/config/vpc.rb +44 -4
  96. data/modules/mu/defaults/Google.yaml +2 -2
  97. data/modules/mu/deploy.rb +13 -10
  98. data/modules/mu/groomer.rb +1 -1
  99. data/modules/mu/groomers/ansible.rb +69 -24
  100. data/modules/mu/groomers/chef.rb +52 -44
  101. data/modules/mu/logger.rb +17 -14
  102. data/modules/mu/master.rb +317 -2
  103. data/modules/mu/master/chef.rb +3 -4
  104. data/modules/mu/master/ldap.rb +3 -3
  105. data/modules/mu/master/ssl.rb +12 -2
  106. data/modules/mu/mommacat.rb +85 -1766
  107. data/modules/mu/mommacat/daemon.rb +394 -0
  108. data/modules/mu/mommacat/naming.rb +366 -0
  109. data/modules/mu/mommacat/storage.rb +689 -0
  110. data/modules/tests/bucket.yml +4 -0
  111. data/modules/tests/{win2k12.yaml → needwork/win2k12.yaml} +0 -0
  112. data/modules/tests/regrooms/aws-iam.yaml +201 -0
  113. data/modules/tests/regrooms/bucket.yml +19 -0
  114. metadata +112 -102
@@ -66,13 +66,16 @@ module MU
66
66
  def log(msg,
67
67
  level=INFO,
68
68
  details: nil,
69
- html: @html,
70
- verbosity: @verbosity,
71
- handle: @handle,
72
- color: @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 @html
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 @html
145
+ if html
143
146
  html_out "#{time} - #{caller_name} - #{msg}", "orange"
144
147
  html_out "&nbsp;#{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 @html
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 @html
168
+ if html
166
169
  html_out "&nbsp;#{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 @html
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 @html
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 @html
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 @html
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 @html
218
+ if html
216
219
  html_out "#{time} - #{caller_name} - #{msg}", "red"
217
220
  html_out "&nbsp;#{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 @html
231
+ if html
229
232
  html_out "#{time} - #{caller_name} - #{msg}"
230
233
  html_out "&nbsp;#{details}" if details
231
234
  elsif color
@@ -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 Exception => e
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 Exception => e
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
@@ -48,7 +48,7 @@ module MU
48
48
  def self.deleteOrg(org)
49
49
  begin
50
50
  Timeout::timeout(45) {
51
- response = chefAPI.delete("organizations/#{org}")
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
- response = chefAPI.delete("users/#{chef_user}")
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
- response = chefAPI.delete("organizations/#{org}/users/#{user}")
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