cloud-mu 3.1.2 → 3.2.0
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 +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
|