cloud-mu 3.1.2 → 3.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Dockerfile +15 -3
- data/ansible/roles/mu-windows/README.md +33 -0
- data/ansible/roles/mu-windows/defaults/main.yml +2 -0
- data/ansible/roles/mu-windows/files/LaunchConfig.json +9 -0
- data/ansible/roles/mu-windows/files/config.xml +76 -0
- data/ansible/roles/mu-windows/handlers/main.yml +2 -0
- data/ansible/roles/mu-windows/meta/main.yml +53 -0
- data/ansible/roles/mu-windows/tasks/main.yml +36 -0
- data/ansible/roles/mu-windows/tests/inventory +2 -0
- data/ansible/roles/mu-windows/tests/test.yml +5 -0
- data/ansible/roles/mu-windows/vars/main.yml +2 -0
- data/bin/mu-adopt +10 -13
- data/bin/mu-azure-tests +57 -0
- data/bin/mu-cleanup +2 -4
- data/bin/mu-configure +52 -0
- data/bin/mu-deploy +3 -3
- data/bin/mu-findstray-tests +25 -0
- data/bin/mu-gen-docs +2 -4
- data/bin/mu-load-config.rb +2 -3
- data/bin/mu-node-manage +15 -16
- data/bin/mu-run-tests +135 -37
- data/cloud-mu.gemspec +22 -20
- data/cookbooks/mu-activedirectory/resources/domain.rb +4 -4
- data/cookbooks/mu-activedirectory/resources/domain_controller.rb +4 -4
- data/cookbooks/mu-tools/libraries/helper.rb +3 -2
- data/cookbooks/mu-tools/libraries/monkey.rb +35 -0
- data/cookbooks/mu-tools/recipes/apply_security.rb +14 -14
- data/cookbooks/mu-tools/recipes/aws_api.rb +9 -0
- data/cookbooks/mu-tools/recipes/eks.rb +2 -2
- data/cookbooks/mu-tools/recipes/google_api.rb +2 -2
- data/cookbooks/mu-tools/recipes/selinux.rb +2 -1
- data/cookbooks/mu-tools/recipes/windows-client.rb +163 -164
- data/cookbooks/mu-tools/resources/disk.rb +1 -1
- data/cookbooks/mu-tools/resources/windows_users.rb +44 -43
- data/extras/clean-stock-amis +25 -19
- data/extras/generate-stock-images +1 -0
- data/extras/image-generators/AWS/win2k12.yaml +18 -13
- data/extras/image-generators/AWS/win2k16.yaml +18 -13
- data/extras/image-generators/AWS/win2k19.yaml +21 -0
- data/extras/image-generators/Google/centos6.yaml +1 -0
- data/extras/image-generators/Google/centos7.yaml +1 -1
- data/modules/mommacat.ru +6 -16
- data/modules/mu.rb +165 -111
- data/modules/mu/adoption.rb +401 -68
- data/modules/mu/cleanup.rb +199 -306
- data/modules/mu/cloud.rb +100 -1632
- data/modules/mu/cloud/database.rb +49 -0
- data/modules/mu/cloud/dnszone.rb +46 -0
- data/modules/mu/cloud/machine_images.rb +212 -0
- data/modules/mu/cloud/providers.rb +81 -0
- data/modules/mu/cloud/resource_base.rb +920 -0
- data/modules/mu/cloud/server.rb +40 -0
- data/modules/mu/cloud/server_pool.rb +1 -0
- data/modules/mu/cloud/ssh_sessions.rb +228 -0
- data/modules/mu/cloud/winrm_sessions.rb +237 -0
- data/modules/mu/cloud/wrappers.rb +165 -0
- data/modules/mu/config.rb +171 -1767
- data/modules/mu/config/alarm.rb +2 -6
- data/modules/mu/config/bucket.rb +4 -4
- data/modules/mu/config/cache_cluster.rb +1 -1
- data/modules/mu/config/collection.rb +4 -4
- data/modules/mu/config/container_cluster.rb +9 -4
- data/modules/mu/config/database.rb +83 -104
- data/modules/mu/config/database.yml +1 -2
- data/modules/mu/config/dnszone.rb +6 -6
- data/modules/mu/config/doc_helpers.rb +516 -0
- data/modules/mu/config/endpoint.rb +4 -4
- data/modules/mu/config/firewall_rule.rb +103 -4
- data/modules/mu/config/folder.rb +4 -4
- data/modules/mu/config/function.rb +3 -3
- data/modules/mu/config/group.rb +4 -4
- data/modules/mu/config/habitat.rb +4 -4
- data/modules/mu/config/loadbalancer.rb +60 -14
- data/modules/mu/config/log.rb +4 -4
- data/modules/mu/config/msg_queue.rb +4 -4
- data/modules/mu/config/nosqldb.rb +4 -4
- data/modules/mu/config/notifier.rb +3 -3
- data/modules/mu/config/ref.rb +365 -0
- data/modules/mu/config/role.rb +4 -4
- data/modules/mu/config/schema_helpers.rb +509 -0
- data/modules/mu/config/search_domain.rb +4 -4
- data/modules/mu/config/server.rb +97 -70
- data/modules/mu/config/server.yml +1 -0
- data/modules/mu/config/server_pool.rb +5 -9
- data/modules/mu/config/storage_pool.rb +1 -1
- data/modules/mu/config/tail.rb +200 -0
- data/modules/mu/config/user.rb +4 -4
- data/modules/mu/config/vpc.rb +70 -27
- data/modules/mu/config/vpc.yml +0 -1
- data/modules/mu/defaults/AWS.yaml +83 -60
- data/modules/mu/defaults/Azure.yaml +1 -0
- data/modules/mu/defaults/Google.yaml +3 -2
- data/modules/mu/deploy.rb +30 -26
- data/modules/mu/groomer.rb +17 -2
- data/modules/mu/groomers/ansible.rb +188 -41
- data/modules/mu/groomers/chef.rb +116 -55
- data/modules/mu/logger.rb +127 -148
- data/modules/mu/master.rb +389 -2
- data/modules/mu/master/chef.rb +3 -4
- data/modules/mu/master/ldap.rb +3 -3
- data/modules/mu/master/ssl.rb +12 -3
- data/modules/mu/mommacat.rb +217 -2612
- data/modules/mu/mommacat/daemon.rb +397 -0
- data/modules/mu/mommacat/naming.rb +473 -0
- data/modules/mu/mommacat/search.rb +495 -0
- data/modules/mu/mommacat/storage.rb +722 -0
- data/modules/mu/{clouds → providers}/README.md +1 -1
- data/modules/mu/{clouds → providers}/aws.rb +271 -112
- data/modules/mu/{clouds → providers}/aws/alarm.rb +5 -3
- data/modules/mu/{clouds → providers}/aws/bucket.rb +26 -22
- data/modules/mu/{clouds → providers}/aws/cache_cluster.rb +33 -67
- data/modules/mu/{clouds → providers}/aws/collection.rb +24 -23
- data/modules/mu/{clouds → providers}/aws/container_cluster.rb +681 -721
- data/modules/mu/providers/aws/database.rb +1744 -0
- data/modules/mu/{clouds → providers}/aws/dnszone.rb +64 -63
- data/modules/mu/{clouds → providers}/aws/endpoint.rb +22 -27
- data/modules/mu/{clouds → providers}/aws/firewall_rule.rb +214 -244
- data/modules/mu/{clouds → providers}/aws/folder.rb +7 -7
- data/modules/mu/{clouds → providers}/aws/function.rb +17 -22
- data/modules/mu/{clouds → providers}/aws/group.rb +23 -23
- data/modules/mu/{clouds → providers}/aws/habitat.rb +17 -14
- data/modules/mu/{clouds → providers}/aws/loadbalancer.rb +57 -48
- data/modules/mu/{clouds → providers}/aws/log.rb +15 -12
- data/modules/mu/{clouds → providers}/aws/msg_queue.rb +17 -16
- data/modules/mu/{clouds → providers}/aws/nosqldb.rb +18 -11
- data/modules/mu/{clouds → providers}/aws/notifier.rb +11 -6
- data/modules/mu/{clouds → providers}/aws/role.rb +112 -86
- data/modules/mu/{clouds → providers}/aws/search_domain.rb +39 -33
- data/modules/mu/{clouds → providers}/aws/server.rb +835 -1133
- data/modules/mu/{clouds → providers}/aws/server_pool.rb +56 -60
- data/modules/mu/{clouds → providers}/aws/storage_pool.rb +24 -42
- data/modules/mu/{clouds → providers}/aws/user.rb +21 -22
- data/modules/mu/{clouds → providers}/aws/userdata/README.md +0 -0
- data/modules/mu/{clouds → providers}/aws/userdata/linux.erb +0 -0
- data/modules/mu/{clouds → providers}/aws/userdata/windows.erb +2 -1
- data/modules/mu/{clouds → providers}/aws/vpc.rb +523 -929
- data/modules/mu/providers/aws/vpc_subnet.rb +286 -0
- data/modules/mu/{clouds → providers}/azure.rb +29 -9
- data/modules/mu/{clouds → providers}/azure/container_cluster.rb +3 -8
- data/modules/mu/{clouds → providers}/azure/firewall_rule.rb +18 -11
- data/modules/mu/{clouds → providers}/azure/habitat.rb +8 -6
- data/modules/mu/{clouds → providers}/azure/loadbalancer.rb +5 -5
- data/modules/mu/{clouds → providers}/azure/role.rb +8 -10
- data/modules/mu/{clouds → providers}/azure/server.rb +95 -48
- data/modules/mu/{clouds → providers}/azure/user.rb +6 -8
- data/modules/mu/{clouds → providers}/azure/userdata/README.md +0 -0
- data/modules/mu/{clouds → providers}/azure/userdata/linux.erb +0 -0
- data/modules/mu/{clouds → providers}/azure/userdata/windows.erb +0 -0
- data/modules/mu/{clouds → providers}/azure/vpc.rb +16 -21
- data/modules/mu/{clouds → providers}/cloudformation.rb +18 -7
- data/modules/mu/{clouds → providers}/cloudformation/alarm.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/cache_cluster.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/collection.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/database.rb +6 -17
- data/modules/mu/{clouds → providers}/cloudformation/dnszone.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/firewall_rule.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/loadbalancer.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/log.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/server.rb +7 -7
- data/modules/mu/{clouds → providers}/cloudformation/server_pool.rb +5 -5
- data/modules/mu/{clouds → providers}/cloudformation/vpc.rb +5 -7
- data/modules/mu/{clouds → providers}/docker.rb +0 -0
- data/modules/mu/{clouds → providers}/google.rb +67 -30
- data/modules/mu/{clouds → providers}/google/bucket.rb +13 -15
- data/modules/mu/{clouds → providers}/google/container_cluster.rb +84 -77
- data/modules/mu/{clouds → providers}/google/database.rb +10 -20
- data/modules/mu/{clouds → providers}/google/firewall_rule.rb +15 -14
- data/modules/mu/{clouds → providers}/google/folder.rb +20 -17
- data/modules/mu/{clouds → providers}/google/function.rb +139 -167
- data/modules/mu/{clouds → providers}/google/group.rb +29 -34
- data/modules/mu/{clouds → providers}/google/habitat.rb +21 -22
- data/modules/mu/{clouds → providers}/google/loadbalancer.rb +18 -20
- data/modules/mu/{clouds → providers}/google/role.rb +92 -58
- data/modules/mu/{clouds → providers}/google/server.rb +242 -155
- data/modules/mu/{clouds → providers}/google/server_pool.rb +25 -44
- data/modules/mu/{clouds → providers}/google/user.rb +95 -31
- data/modules/mu/{clouds → providers}/google/userdata/README.md +0 -0
- data/modules/mu/{clouds → providers}/google/userdata/linux.erb +0 -0
- data/modules/mu/{clouds → providers}/google/userdata/windows.erb +0 -0
- data/modules/mu/{clouds → providers}/google/vpc.rb +103 -79
- data/modules/tests/bucket.yml +4 -0
- data/modules/tests/centos6.yaml +11 -0
- data/modules/tests/centos7.yaml +11 -0
- data/modules/tests/centos8.yaml +12 -0
- data/modules/tests/ecs.yaml +23 -0
- data/modules/tests/includes-and-params.yaml +2 -1
- data/modules/tests/rds.yaml +108 -0
- data/modules/tests/regrooms/aws-iam.yaml +201 -0
- data/modules/tests/regrooms/bucket.yml +19 -0
- data/modules/tests/regrooms/rds.yaml +123 -0
- data/modules/tests/server-with-scrub-muisms.yaml +1 -0
- data/modules/tests/super_simple_bok.yml +1 -3
- data/modules/tests/win2k12.yaml +17 -5
- data/modules/tests/win2k16.yaml +25 -0
- data/modules/tests/win2k19.yaml +25 -0
- data/requirements.txt +1 -0
- data/spec/mu/clouds/azure_spec.rb +2 -2
- metadata +232 -154
- data/extras/image-generators/AWS/windows.yaml +0 -18
- data/modules/mu/clouds/aws/database.rb +0 -1985
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
|
@@ -380,6 +386,7 @@ module MU
|
|
380
386
|
best = nil
|
381
387
|
best_version = nil
|
382
388
|
paths.uniq.each { |path|
|
389
|
+
path.sub!(/^~/, MY_HOME)
|
383
390
|
if File.exist?(path+"/kubectl")
|
384
391
|
version = %x{#{path}/kubectl version --short --client}.chomp.sub(/.*Client version:\s+v/i, '')
|
385
392
|
next if !$?.success?
|
@@ -493,5 +500,385 @@ module MU
|
|
493
500
|
end
|
494
501
|
end
|
495
502
|
|
503
|
+
# Clean a node's entries out of /etc/hosts
|
504
|
+
# @param node [String]: The node's name
|
505
|
+
# @return [void]
|
506
|
+
def self.removeInstanceFromEtcHosts(node)
|
507
|
+
return if MU.mu_user != "mu"
|
508
|
+
hostsfile = "/etc/hosts"
|
509
|
+
FileUtils.copy(hostsfile, "#{hostsfile}.bak-#{MU.deploy_id}")
|
510
|
+
File.open(hostsfile, File::CREAT|File::RDWR, 0644) { |f|
|
511
|
+
f.flock(File::LOCK_EX)
|
512
|
+
newlines = Array.new
|
513
|
+
f.readlines.each { |line|
|
514
|
+
newlines << line if !line.match(/ #{node}(\s|$)/)
|
515
|
+
}
|
516
|
+
f.rewind
|
517
|
+
f.truncate(0)
|
518
|
+
f.puts(newlines)
|
519
|
+
f.flush
|
520
|
+
|
521
|
+
f.flock(File::LOCK_UN)
|
522
|
+
}
|
523
|
+
end
|
524
|
+
|
525
|
+
|
526
|
+
# Insert node names associated with a new instance into /etc/hosts so we
|
527
|
+
# can treat them as if they were real DNS entries. Especially helpful when
|
528
|
+
# Chef/Ohai mistake the proper hostname, e.g. when bootstrapping Windows.
|
529
|
+
# @param public_ip [String]: The node's IP address
|
530
|
+
# @param chef_name [String]: The node's Chef node name
|
531
|
+
# @param system_name [String]: The node's local system name
|
532
|
+
# @return [void]
|
533
|
+
def self.addInstanceToEtcHosts(public_ip, chef_name = nil, system_name = nil)
|
534
|
+
|
535
|
+
# XXX cover ipv6 case
|
536
|
+
if public_ip.nil? or !public_ip.match(/^\d+\.\d+\.\d+\.\d+$/) or (chef_name.nil? and system_name.nil?)
|
537
|
+
raise MuError, "addInstanceToEtcHosts requires public_ip and one or both of chef_name and system_name!"
|
538
|
+
end
|
539
|
+
if chef_name == "localhost" or system_name == "localhost"
|
540
|
+
raise MuError, "Can't set localhost as a name in addInstanceToEtcHosts"
|
541
|
+
end
|
542
|
+
|
543
|
+
if !["mu", "root"].include?(MU.mu_user)
|
544
|
+
response = nil
|
545
|
+
begin
|
546
|
+
response = open("https://127.0.0.1:#{MU.mommaCatPort.to_s}/rest/hosts_add/#{chef_name}/#{public_ip}").read
|
547
|
+
rescue Errno::ECONNRESET, Errno::ECONNREFUSED
|
548
|
+
end
|
549
|
+
if response != "ok"
|
550
|
+
MU.log "Unable to add #{public_ip} to /etc/hosts via MommaCat request", MU::WARN
|
551
|
+
end
|
552
|
+
return
|
553
|
+
end
|
554
|
+
|
555
|
+
File.readlines("/etc/hosts").each { |line|
|
556
|
+
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|$)/))
|
557
|
+
MU.log "Ignoring attempt to add duplicate /etc/hosts entry: #{public_ip} #{chef_name} #{system_name}", MU::DEBUG
|
558
|
+
return
|
559
|
+
end
|
560
|
+
}
|
561
|
+
File.open("/etc/hosts", 'a') { |etc_hosts|
|
562
|
+
etc_hosts.flock(File::LOCK_EX)
|
563
|
+
etc_hosts.puts("#{public_ip} #{chef_name} #{system_name}")
|
564
|
+
etc_hosts.flock(File::LOCK_UN)
|
565
|
+
}
|
566
|
+
MU.log("Added to /etc/hosts: #{public_ip} #{chef_name} #{system_name}")
|
567
|
+
end
|
568
|
+
|
569
|
+
@ssh_semaphore = Mutex.new
|
570
|
+
# Insert a definition for a node into our SSH config.
|
571
|
+
# @param server [MU::Cloud::Server]: The name of the node.
|
572
|
+
# @param names [Array<String>]: Other names that we'd like this host to be known by for SSH purposes
|
573
|
+
# @param ssh_dir [String]: The configuration directory of the SSH config to emit.
|
574
|
+
# @param ssh_conf [String]: A specific SSH configuration file to write entries into.
|
575
|
+
# @param ssh_owner [String]: The preferred owner of the SSH configuration files.
|
576
|
+
# @param timeout [Integer]: An alternate timeout value for connections to this server.
|
577
|
+
# @return [void]
|
578
|
+
def self.addHostToSSHConfig(server,
|
579
|
+
ssh_dir: "#{Etc.getpwuid(Process.uid).dir}/.ssh",
|
580
|
+
ssh_conf: "#{Etc.getpwuid(Process.uid).dir}/.ssh/config",
|
581
|
+
ssh_owner: Etc.getpwuid(Process.uid).name,
|
582
|
+
names: [],
|
583
|
+
timeout: 0
|
584
|
+
)
|
585
|
+
if server.nil?
|
586
|
+
MU.log "Called addHostToSSHConfig without a MU::Cloud::Server object", MU::ERR, details: caller
|
587
|
+
return nil
|
588
|
+
end
|
589
|
+
|
590
|
+
_nat_ssh_key, nat_ssh_user, nat_ssh_host, canonical_ip, ssh_user, ssh_key_name = begin
|
591
|
+
server.getSSHConfig
|
592
|
+
rescue MU::MuError
|
593
|
+
return
|
594
|
+
end
|
595
|
+
|
596
|
+
if ssh_user.nil? or ssh_user.empty?
|
597
|
+
MU.log "Failed to extract ssh_user for #{server.mu_name} addHostToSSHConfig", MU::ERR
|
598
|
+
return
|
599
|
+
end
|
600
|
+
if canonical_ip.nil? or canonical_ip.empty?
|
601
|
+
MU.log "Failed to extract canonical_ip for #{server.mu_name} addHostToSSHConfig", MU::ERR
|
602
|
+
return
|
603
|
+
end
|
604
|
+
if ssh_key_name.nil? or ssh_key_name.empty?
|
605
|
+
MU.log "Failed to extract ssh_key_name for #{server.mu_name} in addHostToSSHConfig", MU::ERR
|
606
|
+
return
|
607
|
+
end
|
608
|
+
|
609
|
+
@ssh_semaphore.synchronize {
|
610
|
+
|
611
|
+
if File.exist?(ssh_conf)
|
612
|
+
File.readlines(ssh_conf).each { |line|
|
613
|
+
if line.match(/^Host #{server.mu_name} /)
|
614
|
+
MU.log("Attempt to add duplicate #{ssh_conf} entry for #{server.mu_name}", MU::WARN)
|
615
|
+
return
|
616
|
+
end
|
617
|
+
}
|
618
|
+
end
|
619
|
+
|
620
|
+
File.open(ssh_conf, 'a', 0600) { |ssh_config|
|
621
|
+
ssh_config.flock(File::LOCK_EX)
|
622
|
+
host_str = "Host #{server.mu_name} #{server.canonicalIP}"
|
623
|
+
if !names.nil? and names.size > 0
|
624
|
+
host_str = host_str+" "+names.join(" ")
|
625
|
+
end
|
626
|
+
ssh_config.puts host_str
|
627
|
+
ssh_config.puts " Hostname #{server.canonicalIP}"
|
628
|
+
if !nat_ssh_host.nil? and server.canonicalIP != nat_ssh_host
|
629
|
+
ssh_config.puts " ProxyCommand ssh -W %h:%p #{nat_ssh_user}@#{nat_ssh_host}"
|
630
|
+
end
|
631
|
+
if timeout > 0
|
632
|
+
ssh_config.puts " ConnectTimeout #{timeout}"
|
633
|
+
end
|
634
|
+
|
635
|
+
ssh_config.puts " User #{ssh_user}"
|
636
|
+
# XXX I'd rather add the host key to known_hosts, but Net::SSH is a little dumb
|
637
|
+
ssh_config.puts " StrictHostKeyChecking no"
|
638
|
+
ssh_config.puts " ServerAliveInterval 60"
|
639
|
+
|
640
|
+
ssh_config.puts " IdentityFile #{ssh_dir}/#{ssh_key_name}"
|
641
|
+
if !File.exist?("#{ssh_dir}/#{ssh_key_name}")
|
642
|
+
MU.log "#{server.mu_name} - ssh private key #{ssh_dir}/#{ssh_key_name} does not exist", MU::WARN
|
643
|
+
end
|
644
|
+
|
645
|
+
ssh_config.flock(File::LOCK_UN)
|
646
|
+
ssh_config.chown(Etc.getpwnam(ssh_owner).uid, Etc.getpwnam(ssh_owner).gid)
|
647
|
+
}
|
648
|
+
MU.log "Wrote #{server.mu_name} ssh key to #{ssh_dir}/config", MU::DEBUG
|
649
|
+
return "#{ssh_dir}/#{ssh_key_name}"
|
650
|
+
}
|
651
|
+
end
|
652
|
+
|
653
|
+
# Clean an IP address out of ~/.ssh/known hosts
|
654
|
+
# @param ip [String]: The IP to remove
|
655
|
+
# @return [void]
|
656
|
+
def self.removeIPFromSSHKnownHosts(ip, noop: false)
|
657
|
+
return if ip.nil?
|
658
|
+
sshdir = "#{MY_HOME}/.ssh"
|
659
|
+
knownhosts = "#{sshdir}/known_hosts"
|
660
|
+
|
661
|
+
if File.exist?(knownhosts) and File.open(knownhosts).read.match(/^#{Regexp.quote(ip)} /)
|
662
|
+
MU.log "Expunging old #{ip} entry from #{knownhosts}", MU::NOTICE
|
663
|
+
if !noop
|
664
|
+
File.open(knownhosts, File::CREAT|File::RDWR, 0600) { |f|
|
665
|
+
f.flock(File::LOCK_EX)
|
666
|
+
newlines = Array.new
|
667
|
+
f.readlines.each { |line|
|
668
|
+
next if line.match(/^#{Regexp.quote(ip)} /)
|
669
|
+
newlines << line
|
670
|
+
}
|
671
|
+
f.rewind
|
672
|
+
f.truncate(0)
|
673
|
+
f.puts(newlines)
|
674
|
+
f.flush
|
675
|
+
f.flock(File::LOCK_UN)
|
676
|
+
}
|
677
|
+
end
|
678
|
+
end
|
679
|
+
end
|
680
|
+
|
681
|
+
# Clean a node's entries out of ~/.ssh/config
|
682
|
+
# @param nodename [String]: The node's name
|
683
|
+
# @return [void]
|
684
|
+
def self.removeHostFromSSHConfig(nodename, noop: false)
|
685
|
+
sshdir = "#{MY_HOME}/.ssh"
|
686
|
+
sshconf = "#{sshdir}/config"
|
687
|
+
|
688
|
+
if File.exist?(sshconf) and File.open(sshconf).read.match(/ #{nodename} /)
|
689
|
+
MU.log "Expunging old #{nodename} entry from #{sshconf}", MU::DEBUG
|
690
|
+
if !noop
|
691
|
+
File.open(sshconf, File::CREAT|File::RDWR, 0600) { |f|
|
692
|
+
f.flock(File::LOCK_EX)
|
693
|
+
newlines = Array.new
|
694
|
+
delete_block = false
|
695
|
+
f.readlines.each { |line|
|
696
|
+
if line.match(/^Host #{nodename}(\s|$)/)
|
697
|
+
delete_block = true
|
698
|
+
elsif line.match(/^Host /)
|
699
|
+
delete_block = false
|
700
|
+
end
|
701
|
+
newlines << line if !delete_block
|
702
|
+
}
|
703
|
+
f.rewind
|
704
|
+
f.truncate(0)
|
705
|
+
f.puts(newlines)
|
706
|
+
f.flush
|
707
|
+
f.flock(File::LOCK_UN)
|
708
|
+
}
|
709
|
+
end
|
710
|
+
end
|
711
|
+
end
|
712
|
+
|
713
|
+
# Evict ssh keys associated with a particular deploy from our ssh config
|
714
|
+
# and key directory.
|
715
|
+
# @param deploy_id [String]
|
716
|
+
# @param noop [Boolean]
|
717
|
+
def self.purgeDeployFromSSH(deploy_id, noop: false)
|
718
|
+
myhome = Etc.getpwuid(Process.uid).dir
|
719
|
+
sshdir = "#{myhome}/.ssh"
|
720
|
+
sshconf = "#{sshdir}/config"
|
721
|
+
ssharchive = "#{sshdir}/archive"
|
722
|
+
|
723
|
+
Dir.mkdir(sshdir, 0700) if !Dir.exist?(sshdir) and !noop
|
724
|
+
Dir.mkdir(ssharchive, 0700) if !Dir.exist?(ssharchive) and !noop
|
725
|
+
|
726
|
+
keyname = "deploy-#{deploy_id}"
|
727
|
+
if File.exist?("#{sshdir}/#{keyname}")
|
728
|
+
MU.log "Moving #{sshdir}/#{keyname} to #{ssharchive}/#{keyname}"
|
729
|
+
if !noop
|
730
|
+
File.rename("#{sshdir}/#{keyname}", "#{ssharchive}/#{keyname}")
|
731
|
+
end
|
732
|
+
end
|
733
|
+
if File.exist?(sshconf) and File.open(sshconf).read.match(/\/deploy\-#{deploy_id}$/)
|
734
|
+
MU.log "Expunging #{deploy_id} from #{sshconf}"
|
735
|
+
if !noop
|
736
|
+
FileUtils.copy(sshconf, "#{ssharchive}/config-#{deploy_id}")
|
737
|
+
File.open(sshconf, File::CREAT|File::RDWR, 0600) { |f|
|
738
|
+
f.flock(File::LOCK_EX)
|
739
|
+
newlines = Array.new
|
740
|
+
delete_block = false
|
741
|
+
f.readlines.each { |line|
|
742
|
+
if line.match(/^Host #{deploy_id}\-/)
|
743
|
+
delete_block = true
|
744
|
+
elsif line.match(/^Host /)
|
745
|
+
delete_block = false
|
746
|
+
end
|
747
|
+
newlines << line if !delete_block
|
748
|
+
}
|
749
|
+
f.rewind
|
750
|
+
f.truncate(0)
|
751
|
+
f.puts(newlines)
|
752
|
+
f.flush
|
753
|
+
f.flock(File::LOCK_UN)
|
754
|
+
}
|
755
|
+
end
|
756
|
+
end
|
757
|
+
# XXX refactor with above? They're similar, ish.
|
758
|
+
hostsfile = "/etc/hosts"
|
759
|
+
if File.open(hostsfile).read.match(/ #{deploy_id}\-/)
|
760
|
+
if Process.uid == 0
|
761
|
+
MU.log "Expunging traces of #{deploy_id} from #{hostsfile}"
|
762
|
+
if !noop
|
763
|
+
FileUtils.copy(hostsfile, "#{hostsfile}.cleanup-#{deploy_id}")
|
764
|
+
File.open(hostsfile, File::CREAT|File::RDWR, 0644) { |f|
|
765
|
+
f.flock(File::LOCK_EX)
|
766
|
+
newlines = Array.new
|
767
|
+
f.readlines.each { |line|
|
768
|
+
newlines << line if !line.match(/ #{deploy_id}\-/)
|
769
|
+
}
|
770
|
+
f.rewind
|
771
|
+
f.truncate(0)
|
772
|
+
f.puts(newlines)
|
773
|
+
f.flush
|
774
|
+
f.flock(File::LOCK_UN)
|
775
|
+
}
|
776
|
+
end
|
777
|
+
else
|
778
|
+
MU.log "Residual /etc/hosts entries for #{deploy_id} must be removed by root user", MU::WARN
|
779
|
+
end
|
780
|
+
end
|
781
|
+
|
782
|
+
end
|
783
|
+
|
784
|
+
# Ensure that the Nagios configuration local to the MU master has been
|
785
|
+
# updated, and make sure Nagios has all of the ssh keys it needs to tunnel
|
786
|
+
# to client nodes.
|
787
|
+
# @return [void]
|
788
|
+
def self.syncMonitoringConfig(blocking = true)
|
789
|
+
return if Etc.getpwuid(Process.uid).name != "root" or (MU.mu_user != "mu" and MU.mu_user != "root")
|
790
|
+
parent_thread_id = Thread.current.object_id
|
791
|
+
nagios_threads = []
|
792
|
+
nagios_threads << Thread.new {
|
793
|
+
MU.dupGlobals(parent_thread_id)
|
794
|
+
realhome = Etc.getpwnam("nagios").dir
|
795
|
+
[NAGIOS_HOME, "#{NAGIOS_HOME}/.ssh"].each { |dir|
|
796
|
+
Dir.mkdir(dir, 0711) if !Dir.exist?(dir)
|
797
|
+
File.chown(Etc.getpwnam("nagios").uid, Etc.getpwnam("nagios").gid, dir)
|
798
|
+
}
|
799
|
+
if realhome != NAGIOS_HOME and Dir.exist?(realhome) and !File.symlink?("#{realhome}/.ssh")
|
800
|
+
File.rename("#{realhome}/.ssh", "#{realhome}/.ssh.#{$$}") if Dir.exist?("#{realhome}/.ssh")
|
801
|
+
File.symlink("#{NAGIOS_HOME}/.ssh", Etc.getpwnam("nagios").dir+"/.ssh")
|
802
|
+
end
|
803
|
+
MU.log "Updating #{NAGIOS_HOME}/.ssh/config..."
|
804
|
+
ssh_lock = File.new("#{NAGIOS_HOME}/.ssh/config.mu.lock", File::CREAT|File::TRUNC|File::RDWR, 0600)
|
805
|
+
ssh_lock.flock(File::LOCK_EX)
|
806
|
+
ssh_conf = File.new("#{NAGIOS_HOME}/.ssh/config.tmp", File::CREAT|File::TRUNC|File::RDWR, 0600)
|
807
|
+
ssh_conf.puts "Host MU-MASTER localhost"
|
808
|
+
ssh_conf.puts " Hostname localhost"
|
809
|
+
ssh_conf.puts " User root"
|
810
|
+
ssh_conf.puts " IdentityFile #{NAGIOS_HOME}/.ssh/id_rsa"
|
811
|
+
ssh_conf.puts " StrictHostKeyChecking no"
|
812
|
+
ssh_conf.close
|
813
|
+
FileUtils.cp("#{Etc.getpwuid(Process.uid).dir}/.ssh/id_rsa", "#{NAGIOS_HOME}/.ssh/id_rsa")
|
814
|
+
File.chown(Etc.getpwnam("nagios").uid, Etc.getpwnam("nagios").gid, "#{NAGIOS_HOME}/.ssh/id_rsa")
|
815
|
+
threads = []
|
816
|
+
|
817
|
+
parent_thread_id = Thread.current.object_id
|
818
|
+
MU::MommaCat.listDeploys.sort.each { |deploy_id|
|
819
|
+
begin
|
820
|
+
# We don't want to use cached litter information here because this is also called by cleanTerminatedInstances.
|
821
|
+
deploy = MU::MommaCat.getLitter(deploy_id)
|
822
|
+
if deploy.ssh_key_name.nil? or deploy.ssh_key_name.empty?
|
823
|
+
MU.log "Failed to extract ssh key name from #{deploy_id} in syncMonitoringConfig", MU::ERR if deploy.kittens.has_key?("servers")
|
824
|
+
next
|
825
|
+
end
|
826
|
+
FileUtils.cp("#{Etc.getpwuid(Process.uid).dir}/.ssh/#{deploy.ssh_key_name}", "#{NAGIOS_HOME}/.ssh/#{deploy.ssh_key_name}")
|
827
|
+
File.chown(Etc.getpwnam("nagios").uid, Etc.getpwnam("nagios").gid, "#{NAGIOS_HOME}/.ssh/#{deploy.ssh_key_name}")
|
828
|
+
if deploy.kittens.has_key?("servers")
|
829
|
+
deploy.kittens["servers"].values.each { |nodeclasses|
|
830
|
+
nodeclasses.values.each { |nodes|
|
831
|
+
nodes.values.each { |server|
|
832
|
+
next if !server.cloud_desc
|
833
|
+
MU.dupGlobals(parent_thread_id)
|
834
|
+
threads << Thread.new {
|
835
|
+
MU::MommaCat.setThreadContext(deploy)
|
836
|
+
MU.log "Adding #{server.mu_name} to #{NAGIOS_HOME}/.ssh/config", MU::DEBUG
|
837
|
+
MU::Master.addHostToSSHConfig(
|
838
|
+
server,
|
839
|
+
ssh_dir: "#{NAGIOS_HOME}/.ssh",
|
840
|
+
ssh_conf: "#{NAGIOS_HOME}/.ssh/config.tmp",
|
841
|
+
ssh_owner: "nagios"
|
842
|
+
)
|
843
|
+
MU.purgeGlobals
|
844
|
+
}
|
845
|
+
}
|
846
|
+
}
|
847
|
+
}
|
848
|
+
end
|
849
|
+
rescue StandardError => e
|
850
|
+
MU.log "#{e.inspect} while generating Nagios SSH config in #{deploy_id}", MU::ERR, details: e.backtrace
|
851
|
+
end
|
852
|
+
}
|
853
|
+
threads.each { |t|
|
854
|
+
t.join
|
855
|
+
}
|
856
|
+
ssh_lock.flock(File::LOCK_UN)
|
857
|
+
ssh_lock.close
|
858
|
+
File.chown(Etc.getpwnam("nagios").uid, Etc.getpwnam("nagios").gid, "#{NAGIOS_HOME}/.ssh/config.tmp")
|
859
|
+
File.rename("#{NAGIOS_HOME}/.ssh/config.tmp", "#{NAGIOS_HOME}/.ssh/config")
|
860
|
+
|
861
|
+
MU.log "Updating Nagios monitoring config, this may take a while..."
|
862
|
+
output = nil
|
863
|
+
if $MU_CFG and !$MU_CFG['master_runlist_extras'].nil?
|
864
|
+
output = %x{#{MU::Groomer::Chef.chefclient} -o 'role[mu-master-nagios-only],#{$MU_CFG['master_runlist_extras'].join(",")}' 2>&1}
|
865
|
+
else
|
866
|
+
output = %x{#{MU::Groomer::Chef.chefclient} -o 'role[mu-master-nagios-only]' 2>&1}
|
867
|
+
end
|
868
|
+
|
869
|
+
if $?.exitstatus != 0
|
870
|
+
MU.log "Nagios monitoring config update returned a non-zero exit code!", MU::ERR, details: output
|
871
|
+
else
|
872
|
+
MU.log "Nagios monitoring config update complete."
|
873
|
+
end
|
874
|
+
}
|
875
|
+
|
876
|
+
if blocking
|
877
|
+
nagios_threads.each { |t|
|
878
|
+
t.join
|
879
|
+
}
|
880
|
+
end
|
881
|
+
end
|
882
|
+
|
496
883
|
end
|
497
884
|
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
|