continuent-tools-core 0.9.0 → 0.10.6

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.
@@ -17,7 +17,8 @@ class TungstenScriptMySQLDatasource < TungstenScriptDatasource
17
17
  end
18
18
 
19
19
  begin
20
- TU.cmd_result("#{@ti.sudo_prefix()}#{get_service_command()} stop")
20
+ stop_command = @ti.setting(TI.setting_key(REPL_SERVICES, @service, "repl_datasource_service_stop"))
21
+ TU.cmd_result("#{@ti.sudo_prefix()}#{stop_command}")
21
22
  rescue CommandError
22
23
  end
23
24
 
@@ -51,7 +52,8 @@ class TungstenScriptMySQLDatasource < TungstenScriptDatasource
51
52
 
52
53
  def _start_server
53
54
  begin
54
- TU.cmd_result("#{@ti.sudo_prefix()}#{get_service_command()} start")
55
+ start_command = @ti.setting(TI.setting_key(REPL_SERVICES, @service, "repl_datasource_service_start"))
56
+ TU.cmd_result("#{@ti.sudo_prefix()}#{start_command}")
55
57
  rescue CommandError
56
58
  end
57
59
 
@@ -94,40 +96,6 @@ class TungstenScriptMySQLDatasource < TungstenScriptDatasource
94
96
  end
95
97
  end
96
98
 
97
- def get_service_command
98
- if @mysql_service_command == nil
99
- if @mysql_service_command == nil
100
- @mysql_service_command = @ti.setting(TI.setting_key(REPL_SERVICES, @service, "repl_datasource_boot_script"))
101
- end
102
- if @mysql_service_command == nil
103
- begin
104
- service_command=TU.cmd_result("which service")
105
- if TU.cmd("#{@ti.sudo_prefix()}test -x #{service_command}")
106
- if TU.cmd("#{@ti.sudo_prefix()}test -x /etc/init.d/mysqld")
107
- @mysql_service_command = "#{service_command} mysqld"
108
- elsif TU.cmd("#{@ti.sudo_prefix()}test -x /etc/init.d/mysql")
109
- @mysql_service_command = "#{service_command} mysql"
110
- else
111
- TU.error "Unable to determine the service command to start/stop mysql"
112
- end
113
- else
114
- if TU.cmd("#{@ti.sudo_prefix()}test -x /etc/init.d/mysqld")
115
- @mysql_service_command = "/etc/init.d/mysqld"
116
- elsif TU.cmd("#{@ti.sudo_prefix()}test -x /etc/init.d/mysql")
117
- @mysql_service_command = "/etc/init.d/mysql"
118
- else
119
- TU.error "Unable to determine the service command to start/stop mysql"
120
- end
121
- end
122
- rescue CommandError
123
- TU.error "Unable to determine the service command to start/stop mysql"
124
- end
125
- end
126
- end
127
-
128
- @mysql_service_command
129
- end
130
-
131
99
  def get_system_user
132
100
  if @mysql_user == nil
133
101
  @mysql_user = get_option("user")
@@ -1,6 +1,6 @@
1
1
  require "open4"
2
2
  require "resolv"
3
- require "ifconfig"
3
+ require "ipparse"
4
4
 
5
5
  class TungstenUtil
6
6
  def initialize()
@@ -283,16 +283,14 @@ class TungstenUtil
283
283
  return cmd_result(command)
284
284
  end
285
285
 
286
- self.synchronize() {
287
- unless defined?(Net::SSH)
288
- begin
289
- require "openssl"
290
- rescue LoadError
291
- raise("Unable to find the Ruby openssl library. Try installing the openssl package for your version of Ruby (libopenssl-ruby#{RUBY_VERSION[0,3]}).")
292
- end
293
- require 'net/ssh'
286
+ unless defined?(Net::SSH)
287
+ begin
288
+ require "openssl"
289
+ rescue LoadError
290
+ raise("Unable to find the Ruby openssl library. Try installing the openssl package for your version of Ruby (libopenssl-ruby#{RUBY_VERSION[0,3]}).")
294
291
  end
295
- }
292
+ require 'net/ssh'
293
+ end
296
294
 
297
295
  ssh_user = get_ssh_user(user)
298
296
  if user != ssh_user
@@ -470,15 +468,15 @@ class TungstenUtil
470
468
  end
471
469
 
472
470
  debug("Search ifconfig for #{ip_addresses.join(', ')}")
473
- ifconfig = IfconfigWrapper.new().parse()
474
- ifconfig.each{
475
- |iface|
471
+ ipparsed = IPParse.new().get_interfaces()
472
+ ipparsed.each{
473
+ |iface, addresses|
476
474
 
477
475
  begin
478
476
  # Do a string comparison so that we only match the address portion
479
- iface.addresses().each{
480
- |a|
481
- if ip_addresses.include?(a.to_s())
477
+ addresses.each{
478
+ |type, details|
479
+ if ip_addresses.include?(details[:address])
482
480
  return true
483
481
  end
484
482
  }
@@ -498,6 +496,7 @@ class TungstenUtil
498
496
  ip_addresses = Timeout.timeout(5) {
499
497
  Resolv.getaddresses(hostname)
500
498
  }
499
+ ip_addresses.delete_if{|ip| ip.to_s() == ""}
501
500
 
502
501
  if ip_addresses.length == 0
503
502
  begin
@@ -528,6 +527,7 @@ class TungstenUtil
528
527
  ip_addresses = Timeout.timeout(5) {
529
528
  Resolv.getaddresses(hostname)
530
529
  }
530
+ ip_addresses.delete_if{|ip| ip.to_s() == ""}
531
531
 
532
532
  if ip_addresses.length == 0
533
533
  begin
@@ -614,9 +614,10 @@ module OfflineServicesScript
614
614
  })
615
615
 
616
616
  add_option(:offline, {
617
- :on => "--offline",
617
+ :on => "--offline String",
618
618
  :help => "Put required replication services offline before processing",
619
- :default => false
619
+ :default => false,
620
+ :parse => method(:parse_boolean_option_blank_is_true)
620
621
  })
621
622
 
622
623
  add_option(:offline_timeout, {
@@ -627,9 +628,10 @@ module OfflineServicesScript
627
628
  })
628
629
 
629
630
  add_option(:online, {
630
- :on => "--online",
631
+ :on => "--online String",
631
632
  :help => "Put required replication services online after successful processing",
632
- :default => false
633
+ :default => false,
634
+ :parse => method(:parse_boolean_option_blank_is_true)
633
635
  })
634
636
  end
635
637
 
@@ -671,21 +673,32 @@ module OfflineServicesScript
671
673
  ds_list.each{
672
674
  |ds|
673
675
  threads << Thread.new{
676
+ use_manager = false
677
+
674
678
  if TI.is_manager?()
675
- begin
676
- status = TI.status(ds)
677
- unless status.is_replication?() == true
678
- get_manager_api.call("#{ds}/#{TI.hostname()}", 'shun')
679
- TU.cmd_result("#{TI.trepctl(ds)} offline")
680
- else
681
- TU.cmd_result("#{TI.trepctl(ds)} offline")
679
+ status = TI.status(ds)
680
+
681
+ # Make sure this is actually a physical dataservice
682
+ if status.is_physical?()
683
+ # Does this datasource actually appear in the status
684
+ # It may not if the host hasn't been provisioned
685
+ if status.datasources().index(TI.hostname()) != nil
686
+ use_manager = true
682
687
  end
683
- rescue => e
684
- TU.exception(e)
685
- raise("Unable to put replication services offline")
686
688
  end
687
- else
689
+ end
690
+
691
+ begin
692
+ if use_manager == true
693
+ get_manager_api.call("#{ds}/#{TI.hostname()}", 'shun')
694
+ end
695
+
696
+ # The trepctl offline command is required even when using
697
+ # the manager because shun doesn't affect the replicator
688
698
  TU.cmd_result("#{TI.trepctl(ds)} offline")
699
+ rescue => e
700
+ TU.exception(e)
701
+ raise("Unable to put replication services offline")
689
702
  end
690
703
  }
691
704
  }
@@ -751,23 +764,36 @@ module OfflineServicesScript
751
764
  end
752
765
 
753
766
  if online == true
767
+ use_manager = false
768
+
754
769
  if TI.is_manager?()
755
- begin
756
- status = TI.status(ds)
757
- unless status.is_replication?() == true
758
- TU.cmd_result("echo 'datasource #{TI.hostname()} recover' | #{TI.cctrl()}")
759
- #get_manager_api.call("#{ds}/#{TI.hostname()}", 'recover')
760
- else
761
- TU.cmd_result("#{TI.trepctl(ds)} online")
770
+ status = TI.status(ds)
771
+
772
+ # Make sure this is actually a physical dataservice
773
+ if status.is_physical?()
774
+ # Does this datasource actually appear in the status
775
+ # It may not if the host hasn't been provisioned
776
+ if status.datasources().index(TI.hostname()) != nil
777
+ use_manager = true
762
778
  end
763
- rescue => e
764
- TU.exception(e)
765
- raise("The #{ds} replication service did not come online")
766
779
  end
767
- else
768
- TU.cmd_result("#{TI.trepctl(ds)} online")
769
780
  end
770
781
 
782
+ begin
783
+ if use_manager == true
784
+ # Bring the replicator and the datasource ONLINE
785
+ TU.cmd_result("echo 'datasource #{TI.hostname()} recover' | #{TI.cctrl()}")
786
+ else
787
+ # Bring just the replicator ONLINE
788
+ TU.cmd_result("#{TI.trepctl(ds)} online")
789
+ end
790
+ rescue => e
791
+ TU.exception(e)
792
+ raise("The #{ds} replication service did not come online")
793
+ end
794
+
795
+ # Verify the replicator is in fact ONLINE since the recover
796
+ # command may have not returned the right error
771
797
  unless TI.trepctl_value(ds, "state") == "ONLINE"
772
798
  raise("Unable to put the #{ds} replication service online")
773
799
  end
@@ -871,34 +897,6 @@ module MySQLServiceScript
871
897
  if @options[:mysqluser].to_s() == ""
872
898
  @options[:mysqluser] = "mysql"
873
899
  end
874
-
875
- if @options[:mysql_service_command] == nil
876
- @options[:mysql_service_command] = TI.setting(TI.setting_key(REPL_SERVICES, @options[:service], "repl_datasource_boot_script"))
877
- end
878
- if @options[:mysql_service_command] == nil
879
- begin
880
- service_command=TU.cmd_result("which service")
881
- if TU.cmd("#{sudo_prefix()}test -x #{service_command}")
882
- if TU.cmd("#{sudo_prefix()}test -x /etc/init.d/mysqld")
883
- @options[:mysql_service_command] = "#{service_command} mysqld"
884
- elsif TU.cmd("#{sudo_prefix()}test -x /etc/init.d/mysql")
885
- @options[:mysql_service_command] = "#{service_command} mysql"
886
- else
887
- TU.error "Unable to determine the service command to start/stop mysql"
888
- end
889
- else
890
- if TU.cmd("#{sudo_prefix()}test -x /etc/init.d/mysqld")
891
- @options[:mysql_service_command] = "/etc/init.d/mysqld"
892
- elsif TU.cmd("#{sudo_prefix()}test -x /etc/init.d/mysql")
893
- @options[:mysql_service_command] = "/etc/init.d/mysql"
894
- else
895
- TU.error "Unable to determine the service command to start/stop mysql"
896
- end
897
- end
898
- rescue CommandError
899
- TU.error "Unable to determine the service command to start/stop mysql"
900
- end
901
- end
902
900
  end
903
901
  end
904
902
 
@@ -1019,76 +1017,14 @@ module MySQLServiceScript
1019
1017
  end
1020
1018
 
1021
1019
  def start_mysql_server
1022
- TU.notice("Start the MySQL service")
1023
- begin
1024
- TU.cmd_result("#{sudo_prefix()}#{@options[:mysql_service_command]} start")
1025
- rescue CommandError
1026
- end
1027
-
1028
- # Wait 30 seconds for the MySQL service to be responsive
1029
- begin
1030
- Timeout.timeout(30) {
1031
- while true
1032
- begin
1033
- if get_mysql_result("SELECT 1") != nil
1034
- break
1035
- end
1036
-
1037
- # Pause for a second before running again
1038
- sleep 1
1039
- rescue
1040
- end
1041
- end
1042
- }
1043
- rescue Timeout::Error
1044
- raise "The MySQL server has taken too long to start"
1045
- end
1020
+ ds = TI.datasource(@options[:service])
1021
+ ds.start()
1046
1022
  end
1047
1023
 
1048
1024
  # Make sure that the mysql server is stopped by stopping it and checking
1049
1025
  # the process has disappeared
1050
1026
  def stop_mysql_server
1051
- TU.notice("Stop the MySQL service")
1052
- begin
1053
- pid_file = get_mysql_variable("pid_file")
1054
- pid = TU.cmd_result("#{sudo_prefix()}cat #{pid_file}")
1055
- rescue CommandError
1056
- pid = ""
1057
- end
1058
-
1059
- begin
1060
- TU.cmd_result("#{sudo_prefix()}#{@options[:mysql_service_command]} stop")
1061
- rescue CommandError
1062
- end
1063
-
1064
- begin
1065
- # Verify that the stop command worked properly
1066
- # We are expecting an error so we have to catch the exception
1067
- TU.cmd_result("#{get_mysql_command()} -e \"select 1\" > /dev/null 2>&1")
1068
- raise "Unable to properly shutdown the MySQL service"
1069
- rescue CommandError
1070
- end
1071
-
1072
- # We saw issues where MySQL would not close completely. This will
1073
- # watch the PID and make sure it does not appear
1074
- unless pid.to_s() == ""
1075
- begin
1076
- TU.debug("Verify that the MySQL pid has gone away")
1077
- Timeout.timeout(30) {
1078
- pid_missing = false
1079
-
1080
- while pid_missing == false do
1081
- begin
1082
- TU.cmd_result("#{sudo_prefix()}ps -p #{pid}")
1083
- sleep 5
1084
- rescue CommandError
1085
- pid_missing = true
1086
- end
1087
- end
1088
- }
1089
- rescue Timeout::Error
1090
- raise "Unable to verify that MySQL has fully shutdown"
1091
- end
1092
- end
1027
+ ds = TI.datasource(@options[:service])
1028
+ ds.stop()
1093
1029
  end
1094
1030
  end
@@ -14,7 +14,6 @@ class TungstenUtil
14
14
  @force = false
15
15
  @json_interface = false
16
16
  @json_message_cache = []
17
- @mutex = Mutex.new
18
17
 
19
18
  # Create a temporary file to hold log contents
20
19
  @log = Tempfile.new("tlog")
@@ -65,8 +64,6 @@ class TungstenUtil
65
64
 
66
65
  if val_parts[0] == "timeout"
67
66
  val_parts[1] = val_parts[1].to_i
68
- elsif val_parts[0] == "verbose"
69
- val_parts[1] = val_parts[1].to_sym
70
67
  end
71
68
 
72
69
  @ssh_options[val_parts[0].to_sym] = val_parts[1]
@@ -629,10 +626,4 @@ class TungstenUtil
629
626
 
630
627
  return hash
631
628
  end
632
-
633
- def synchronize(&block)
634
- @mutex.synchronize do
635
- block.call()
636
- end
637
- end
638
629
  end
@@ -0,0 +1,141 @@
1
+ class AWSEC2TungstenDirectoryProvider < TungstenDirectoryProvider
2
+ DEFAULT_HOSTNAME_TAG = "Name"
3
+
4
+ def self.get_regex()
5
+ "aws\.ec2.*"
6
+ end
7
+
8
+ def get_entries(aws_info)
9
+ hostname_tag = DEFAULT_HOSTNAME_TAG
10
+ require_hostname_tag = false
11
+ aws_entries = {}
12
+
13
+ if aws_info.has_key?("hostname_tag")
14
+ hostname_tag = aws_info["hostname_tag"]
15
+
16
+ if aws_info.has_key?("require_hostname_tag") && aws_info["require_hostname_tag"].to_s() == "false"
17
+ if aws_info["hostname_tag"] == DEFAULT_HOSTNAME_TAG
18
+ # Only allow the use of DEFAULT_HOSTNAME_TAG
19
+ require_hostname_tag = true
20
+ else
21
+ # Allow the use of the given tag and DEFAULT_HOSTNAME_TAG
22
+ require_hostname_tag = false
23
+ end
24
+ else
25
+ # Only allow the use of DEFAULT_HOSTNAME_TAG
26
+ require_hostname_tag = true
27
+ end
28
+ end
29
+
30
+ unless defined?(AWS)
31
+ begin
32
+ gem 'aws-sdk', '>=1.14.0', '<2.0.0'
33
+ require 'aws/ec2'
34
+ rescue LoadError
35
+ raise "The aws-sdk Ruby gem or rubygem-aws-sdk package is required for this class"
36
+ end
37
+ end
38
+ AWS.eager_autoload!(AWS::EC2)
39
+
40
+ if aws_info.has_key?("access_key_id")
41
+ AWS.config({
42
+ :access_key_id => aws_info["access_key_id"]
43
+ })
44
+ end
45
+ if aws_info.has_key?("secret_access_key")
46
+ AWS.config({
47
+ :secret_access_key => aws_info["secret_access_key"]
48
+ })
49
+ end
50
+ if aws_info.has_key?("proxy_uri")
51
+ AWS.config({
52
+ :proxy_uri => aws_info["proxy_uri"]
53
+ })
54
+ end
55
+ ec2 = AWS::EC2.new()
56
+
57
+ region_index = -1
58
+ region_threads = []
59
+ region_results = []
60
+
61
+ if aws_info.has_key?("regions")
62
+ regions = aws_info["regions"]
63
+ if regions.is_a?(String)
64
+ regions = regions.split(",")
65
+ end
66
+ else
67
+ regions = ec2.regions.map(&:name)
68
+ end
69
+ regions.each{|r|
70
+ region_threads << Thread.new{
71
+ index = Thread.exclusive{ (region_index = region_index+1) }
72
+ region = regions[index]
73
+ region_results[index] = {}
74
+ TU.debug("Collect ec2_hosts from #{region}")
75
+
76
+ begin
77
+ region_ec2 = AWS::EC2.new(:region => region)
78
+ instances = region_ec2.instances().filter('instance-state-name', "running")
79
+
80
+ if aws_info.has_key?("tag_key")
81
+ if aws_info.has_key?("tag_value")
82
+ instances = instances.with_tag(aws_info["tag_key"], aws_info["tag_value"])
83
+ else
84
+ instances = instances.tagged(aws_info["tag_key"])
85
+ end
86
+ else
87
+ instances = instances.tagged('tungsten-ServerType')
88
+ end
89
+ instances.each{
90
+ |ins|
91
+ tags = ins.tags.to_h()
92
+
93
+ name = tags.to_h()[hostname_tag]
94
+
95
+ if name.to_s() == "" && require_hostname_tag == false
96
+ # Allow the DEFAULT_HOSTNAME_TAG to be used as a backup
97
+ name = tags.to_h()[DEFAULT_HOSTNAME_TAG]
98
+ end
99
+
100
+ if name.to_s() == ""
101
+ TU.error("Unable to identify the hostname for #{ins.id} in #{region}")
102
+ end
103
+
104
+
105
+ if ins.vpc_id != nil
106
+ location = ins.availability_zone + "." + ins.vpc_id
107
+ else
108
+ location = ins.availability_zone
109
+ end
110
+
111
+ TU.debug("Found #{ins.id}")
112
+ region_results[index][name] = {
113
+ 'id' => ins.id.to_s(),
114
+ 'hostname' => name,
115
+ 'location' => location,
116
+ 'public-address' => ins.public_ip_address,
117
+ 'private-address' => ins.private_ip_address,
118
+ 'tags' => tags.to_h(),
119
+ 'provider' => "aws.ec2",
120
+ 'autodetect-key' => @key
121
+ }
122
+ }
123
+ rescue AWS::EC2::Errors::AuthFailure => af
124
+ TU.debug("Unable to find instances in #{region}: #{af.message}. Operation will continue.")
125
+ rescue => e
126
+ TU.debug("Error finding instances in #{region}: #{e.message}")
127
+ raise e
128
+ end
129
+ }
130
+ }
131
+
132
+ region_threads.each{|t| t.join() }
133
+
134
+ region_results.each{
135
+ |region_result|
136
+ aws_entries.merge!(region_result)
137
+ }
138
+
139
+ aws_entries
140
+ end
141
+ end