continuent-tools-core 0.11.0 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 066d8434e623f609bba0d8b314fb6fa388968013
4
- data.tar.gz: a86daaa05f7ce16f95f050b34bc6a70c9d310eaf
3
+ metadata.gz: f43c9a9d090fbde883cdc8805505da41d06e63ef
4
+ data.tar.gz: 7fe7ba956951f4e6eb3704fdd946550efac0fc8c
5
5
  SHA512:
6
- metadata.gz: ca7e9ca391f2b1d6be6981fdbe2b41816c9a3feda3b14fb8dd665ce0921be3e546fbeab34bbdb9f83183e97f2221e0f063b2e1cff93623fab8d0b5b820a386db
7
- data.tar.gz: 29747f8be2ffed8945eeaacbd8906afe27fdee95fb4971470e4422d6011788820fd5ec064acfa01deca801041f4b470584405e849148e81bf13c460d6259104f
6
+ metadata.gz: 239f531642feb97d8512c03e09cf0628e8cc89b2bfd475825f8cddb96e3bf7c023d5d1c31f0388b16e165a20fcb5fa36a19c05172446164c1663d23bbd2fc119
7
+ data.tar.gz: 37f6e77d3e75cc0470ff79bacc1451668c87c9d86e96abcde3dcc34e83f01df978c308fe467432a8247109f577e18d3bfc5018c5986e68d12dd326d0cf4f7c13
@@ -164,7 +164,7 @@ class TungstenDirectory
164
164
  entry["id"] = id
165
165
  entry["tags"].each{
166
166
  |k,v|
167
- v = v.split(",")
167
+ v = v.to_s().split(",")
168
168
  if v.size() > 1
169
169
  entry["tags"][k] = v
170
170
  end
data/bin/tungsten_policy CHANGED
@@ -31,18 +31,18 @@ class TungstenMigrateSchema
31
31
 
32
32
  def main
33
33
  if opt(:set) != nil
34
- cmd = nil
35
- case opt(:set).downcase()
36
- when "maintenance"
37
- cmd = "setmaintenance"
38
- when "automatic"
39
- cmd = "setautomatic"
40
- when "manual"
41
- cmd = "setmanual"
34
+ commands = []
35
+ if opt(:service).to_s() != ""
36
+ commands << "use #{opt(:service)}"
42
37
  end
38
+ commands << "set policy #{opt(:set)}"
43
39
 
44
- mgr = TungstenDataserviceManager.new(TI.mgr_api_uri())
45
- mgr.call(opt(:service), cmd)
40
+ cmd = "echo '#{commands.join(';')}' | #{TI.cctrl()}"
41
+ result = TU.cmd_result(cmd, true)
42
+
43
+ unless result =~ /policy mode is now #{opt(:set).upcase()}/
44
+ raise MessageError.new("There was an error setting the policy")
45
+ end
46
46
  end
47
47
 
48
48
  status = TungstenStatus.new(TI, opt(:service))
@@ -69,6 +69,32 @@ class TungstenMigrateSchema
69
69
  unless TU.is_valid?()
70
70
  return TU.is_valid?()
71
71
  end
72
+
73
+ if opt(:set) != nil
74
+ opt(:set, opt(:set).downcase())
75
+ case opt(:set)
76
+ when "maintenance"
77
+ # Do nothing
78
+ when "automatic"
79
+ # Do nothing
80
+ when "manual"
81
+ # Do nothing
82
+ else
83
+ TU.error("Unable to set policy to #{opt(:set)}")
84
+ end
85
+ end
86
+
87
+ if TI.dataservices().size() > 1
88
+ if opt(:service).to_s() == ""
89
+ TU.error("The --service argument is required because multiple dataservices are availble.")
90
+ end
91
+ end
92
+
93
+ if opt(:service) != nil
94
+ unless TI.dataservices().include?(opt(:service))
95
+ TU.error("The #{opt(:service)} dataservice is not valid")
96
+ end
97
+ end
72
98
  end
73
99
 
74
100
  def script_name
@@ -0,0 +1,106 @@
1
+ # VMware Continuent Tungsten Replicator
2
+ # Copyright (C) 2015 VMware, Inc. All rights reserved.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+ # Initial developer(s): Jeff Mace
17
+
18
+ class DarwinIPParsePlatform < IPParsePlatform
19
+ def self.supports_platform?(platform)
20
+ if platform.downcase() =~ /darwin/
21
+ true
22
+ else
23
+ false
24
+ end
25
+ end
26
+
27
+ def get_raw_ip_configuration
28
+ path = `which ifconfig 2>/dev/null`.chomp()
29
+ if path == ""
30
+ path = "/sbin/ifconfig"
31
+ end
32
+
33
+ results = `export LANG=en_US; #{path} -a`
34
+ if results == false
35
+ raise "Unable to collect IP configuration from ifconfig"
36
+ else
37
+ return results
38
+ end
39
+ end
40
+
41
+ def parse(raw)
42
+ name_regex = Regexp.compile(/^([a-zA-Z0-9]+):/)
43
+ ether_regex = Regexp.compile(/ether (a-f0-9:)*/)
44
+ flags_regex = Regexp.compile(/flags=([0-9]+)\<([A-Z,]+)\>/)
45
+ inet4_regex1 = Regexp.compile(/inet ([0-9\.]+)[ ]+netmask 0x([a-f0-9]{8})[ ]+(broadcast [0-9\.]+)?/)
46
+ inet6_regex1 = Regexp.compile(/inet6 ([a-f0-9:]+)%[a-z0-9]*[ ]*prefixlen ([0-9]+)/)
47
+
48
+ all_interfaces = []
49
+ interface = []
50
+
51
+ raw.split("\n").each{
52
+ |line|
53
+ if name_regex.match(line)
54
+ if interface.size() > 0
55
+ all_interfaces << interface.join("\n")
56
+ end
57
+ interface = [line]
58
+ else
59
+ interface << line
60
+ end
61
+ }
62
+ if interface.size() > 0
63
+ all_interfaces << interface.join("\n")
64
+ end
65
+
66
+ all_interfaces.each{
67
+ |ifconfig|
68
+ include_interface = false
69
+
70
+ begin
71
+ if ether_regex.match(ifconfig)
72
+ include_interface = true
73
+ end
74
+ rescue
75
+ # Catch the exception and move on
76
+ end
77
+
78
+ if include_interface == false
79
+ next
80
+ end
81
+
82
+ name = name_regex.match(ifconfig)[1]
83
+ if name == nil
84
+ raise "Unable to parse IP configuration because a valid name does not exist"
85
+ end
86
+
87
+ m1 = inet4_regex1.match(ifconfig)
88
+ if m1
89
+ netmask = [
90
+ m1[2][0,2].to_i(16),
91
+ m1[2][2,2].to_i(16),
92
+ m1[2][4,2].to_i(16),
93
+ m1[2][6,2].to_i(16),
94
+ ]
95
+ add_ipv4(name, m1[1], netmask.join('.'))
96
+ end
97
+
98
+ m1 = inet6_regex1.match(ifconfig)
99
+ if m1
100
+ add_ipv6(name, m1[1], m1[2])
101
+ end
102
+ }
103
+
104
+ return @interfaces
105
+ end
106
+ end
@@ -5,6 +5,10 @@ class TungstenScriptDatasource
5
5
  @is_direct = is_direct
6
6
  end
7
7
 
8
+ def title
9
+ raise "Undefined function: #{self.class.name()}.title"
10
+ end
11
+
8
12
  def can_manage_service?
9
13
  false
10
14
  end
@@ -26,7 +30,7 @@ class TungstenScriptDatasource
26
30
  return
27
31
  end
28
32
 
29
- TU.notice("Stop the #{self.class.name()} service")
33
+ TU.notice("Stop the #{self.title()} service")
30
34
  _stop_server()
31
35
  end
32
36
 
@@ -47,7 +51,7 @@ class TungstenScriptDatasource
47
51
  return
48
52
  end
49
53
 
50
- TU.notice("Start the #{self.class.name()} service")
54
+ TU.notice("Start the #{self.title()} service")
51
55
  _start_server()
52
56
  end
53
57
 
@@ -82,4 +86,70 @@ class TungstenScriptDatasource
82
86
  def sql_result(sql)
83
87
  @ti.sql_result(@service, sql, @is_direct)
84
88
  end
89
+
90
+ def url
91
+ begin
92
+ TU.log_cmd_results?(false)
93
+ if @is_direct == true
94
+ return @ti.setting(@ti.setting_key(REPL_SERVICES, @service, "repl_direct_datasource_jdbcqueryurl"))
95
+ else
96
+ return @ti.setting(@ti.setting_key(REPL_SERVICES, @service, "repl_datasource_jdbcqueryurl"))
97
+ end
98
+ ensure
99
+ TU.log_cmd_results?(true)
100
+ end
101
+ end
102
+
103
+ def host
104
+ begin
105
+ TU.log_cmd_results?(false)
106
+ if @is_direct == true
107
+ return @ti.setting(@ti.setting_key(REPL_SERVICES, @service, "repl_direct_datasource_host"))
108
+ else
109
+ return @ti.setting(@ti.setting_key(REPL_SERVICES, @service, "repl_datasource_host"))
110
+ end
111
+ ensure
112
+ TU.log_cmd_results?(true)
113
+ end
114
+ end
115
+
116
+ def port
117
+ begin
118
+ TU.log_cmd_results?(false)
119
+ if @is_direct == true
120
+ return @ti.setting(@ti.setting_key(REPL_SERVICES, @service, "repl_direct_datasource_port"))
121
+ else
122
+ return @ti.setting(@ti.setting_key(REPL_SERVICES, @service, "repl_datasource_port"))
123
+ end
124
+ ensure
125
+ TU.log_cmd_results?(true)
126
+ end
127
+ end
128
+
129
+ def user
130
+ begin
131
+ TU.log_cmd_results?(false)
132
+ if @is_direct == true
133
+ return @ti.setting(@ti.setting_key(REPL_SERVICES, @service, "repl_direct_datasource_user"))
134
+ else
135
+ return @ti.setting(@ti.setting_key(REPL_SERVICES, @service, "repl_datasource_user"))
136
+ end
137
+ ensure
138
+ TU.log_cmd_results?(true)
139
+ end
140
+ end
141
+
142
+ def password
143
+ begin
144
+ # Disable logging of command results so the password doesn't end up in a log file
145
+ TU.log_cmd_results?(false)
146
+ if @is_direct == true
147
+ return @ti.setting(@ti.setting_key(REPL_SERVICES, @service, "repl_direct_datasource_password"))
148
+ else
149
+ return @ti.setting(@ti.setting_key(REPL_SERVICES, @service, "repl_datasource_password"))
150
+ end
151
+ ensure
152
+ TU.log_cmd_results?(true)
153
+ end
154
+ end
85
155
  end
@@ -8,6 +8,10 @@ class TungstenScriptMySQLDatasource < TungstenScriptDatasource
8
8
  end
9
9
  end
10
10
 
11
+ def title
12
+ "MySQL"
13
+ end
14
+
11
15
  def _stop_server
12
16
  begin
13
17
  pid_file = get_variable("pid_file")
data/lib/tungsten/exec.rb CHANGED
@@ -445,46 +445,51 @@ class TungstenUtil
445
445
  end
446
446
 
447
447
  def is_localhost?(hostname)
448
- if hostname == DEFAULTS
449
- return false
450
- end
451
-
452
448
  @_is_localhost_cache ||= {}
453
449
  unless @_is_localhost_cache.has_key?(hostname)
454
450
  @_is_localhost_cache[hostname] = _is_localhost?(hostname)
455
451
  end
456
-
452
+
457
453
  return @_is_localhost_cache[hostname]
458
454
  end
459
455
 
460
456
  def _is_localhost?(hostname)
461
- if hostname == hostname()
462
- return true
463
- end
464
-
465
- ip_addresses = get_ip_addresses(hostname)
466
- if ip_addresses == false
457
+ case hostname
458
+ when DEFAULTS
467
459
  return false
468
- end
460
+ when hostname()
461
+ return true
462
+ when "localhost"
463
+ return true
464
+ when "127.0.0.1"
465
+ return true
466
+ when "::1"
467
+ return true
468
+ else
469
+ ip_addresses = get_ip_addresses(hostname)
470
+ if ip_addresses == false
471
+ return false
472
+ end
469
473
 
470
- debug("Search ifconfig for #{ip_addresses.join(', ')}")
471
- ipparsed = IPParse.new().get_interfaces()
472
- ipparsed.each{
473
- |iface, addresses|
474
+ debug("Search ifconfig for #{ip_addresses.join(', ')}")
475
+ ipparsed = IPParse.new().get_interfaces()
476
+ ipparsed.each{
477
+ |iface, addresses|
474
478
 
475
- begin
476
- # Do a string comparison so that we only match the address portion
477
- addresses.each{
478
- |type, details|
479
- if ip_addresses.include?(details[:address])
480
- return true
481
- end
482
- }
483
- rescue ArgumentError
484
- end
485
- }
479
+ begin
480
+ # Do a string comparison so that we only match the address portion
481
+ addresses.each{
482
+ |type, details|
483
+ if ip_addresses.include?(details[:address])
484
+ return true
485
+ end
486
+ }
487
+ rescue ArgumentError
488
+ end
489
+ }
486
490
 
487
- false
491
+ return false
492
+ end
488
493
  end
489
494
 
490
495
  def get_ip_addresses(hostname)
@@ -381,22 +381,14 @@ class TungstenInstall
381
381
  raise "Unable to run SQL command for the #{service} dataservice. The datasource type does not support SQL commands."
382
382
  end
383
383
 
384
+ ds = datasource(service, use_direct_extractor)
385
+ sql_results_from_url(sql, ds.url(), ds.user(), ds.password())
386
+ end
387
+
388
+ def sql_results_from_url(sql, url, user, password)
384
389
  cfg = nil
385
390
  command = nil
386
391
  begin
387
- # Disable logging of command results so the password doesn't end up in a log file
388
- TU.log_cmd_results?(false)
389
- if use_direct_extractor == true
390
- url= setting(setting_key(REPL_SERVICES, service, "repl_direct_datasource_jdbcqueryurl"))
391
- user = setting(setting_key(REPL_SERVICES, service, "repl_direct_datasource_user"))
392
- password = setting(setting_key(REPL_SERVICES, service, "repl_direct_datasource_password"))
393
- else
394
- url = setting(setting_key(REPL_SERVICES, service, "repl_datasource_jdbcqueryurl"))
395
- user = setting(setting_key(REPL_SERVICES, service, "repl_datasource_user"))
396
- password = setting(setting_key(REPL_SERVICES, service, "repl_datasource_password"))
397
- end
398
- TU.log_cmd_results?(true)
399
-
400
392
  cfg = Tempfile.new("cnf")
401
393
  cfg.puts("url=#{url}")
402
394
  cfg.puts("user=#{user}")
@@ -443,6 +435,16 @@ class TungstenInstall
443
435
  def sql_result(service, sql, use_direct_extractor = false)
444
436
  results = sql_results(service, sql, use_direct_extractor)
445
437
 
438
+ return_first_result(results)
439
+ end
440
+
441
+ def sql_result_from_url(sql, url, user, password)
442
+ results = sql_results_from_url(sql, url, user, password)
443
+
444
+ return_first_result(results)
445
+ end
446
+
447
+ def return_first_result(results)
446
448
  if results.size() == 0
447
449
  raise "No results were returned by #{sql}"
448
450
  end
@@ -53,6 +53,7 @@ module TungstenScript
53
53
  TU.debug("Begin #{$0} #{ARGV.join(' ')}")
54
54
 
55
55
  begin
56
+ prepare_environment()
56
57
  configure()
57
58
  @option_definitions.each{
58
59
  |option_key,definition|
@@ -134,6 +135,24 @@ module TungstenScript
134
135
  })
135
136
  end
136
137
 
138
+ def prepare_environment
139
+ target_umask = nil
140
+ if TI != nil
141
+ install_umask = TI.setting(TI.setting_key(HOSTS, "file_protection_umask"))
142
+ if install_umask.to_s() != ""
143
+ target_umask = install_umask.to_i(8)
144
+ end
145
+ else
146
+ library_mode = sprintf("%o", File.stat(File.dirname(__FILE__)).mode)
147
+ library_umask = 777 - library_mode[-3,3].to_i()
148
+ target_umask = sprintf("%04d", library_umask).to_i(8)
149
+ end
150
+
151
+ if target_umask != nil
152
+ File.umask(target_umask)
153
+ end
154
+ end
155
+
137
156
  def opt(option_key, value = nil)
138
157
  if value != nil
139
158
  @options[option_key] = value
@@ -614,7 +633,7 @@ module OfflineServicesScript
614
633
  })
615
634
 
616
635
  add_option(:offline, {
617
- :on => "--offline String",
636
+ :on => "--offline [String]",
618
637
  :help => "Put required replication services offline before processing",
619
638
  :default => false,
620
639
  :parse => method(:parse_boolean_option_blank_is_true)
@@ -628,7 +647,7 @@ module OfflineServicesScript
628
647
  })
629
648
 
630
649
  add_option(:online, {
631
- :on => "--online String",
650
+ :on => "--online [String]",
632
651
  :help => "Put required replication services online after successful processing",
633
652
  :default => false,
634
653
  :parse => method(:parse_boolean_option_blank_is_true)
@@ -690,7 +709,7 @@ module OfflineServicesScript
690
709
 
691
710
  begin
692
711
  if use_manager == true
693
- get_manager_api.call("#{ds}/#{TI.hostname()}", 'shun')
712
+ TU.cmd_result("echo 'datasource #{TI.hostname()} shun' | #{TI.cctrl()}")
694
713
  end
695
714
 
696
715
  # The trepctl offline command is required even when using
@@ -708,8 +727,20 @@ module OfflineServicesScript
708
727
  raise("The replication #{TU.pluralize(ds_list, "service", "services")} #{TU.pluralize(ds_list, "is", "are")} taking too long to go offline. Check the status for more information or use the --offline-timeout argument.")
709
728
  end
710
729
  end
730
+ end
731
+
732
+ begin
733
+ clear_logs = opt(:clear_logs)
734
+ if clear_logs_during_prepare() == false
735
+ clear_logs = false
736
+ end
737
+
738
+ if clear_logs == true
739
+ cleanup_services(false, clear_logs)
740
+ end
711
741
  rescue => e
712
742
  TU.exception(e)
743
+ code = 1
713
744
  end
714
745
  end
715
746
  end
@@ -717,10 +748,15 @@ module OfflineServicesScript
717
748
  def cleanup(code = 0)
718
749
  if initialized?() == true && TI != nil && code == 0
719
750
  begin
751
+ clear_logs = opt(:clear_logs)
752
+ if clear_logs_during_prepare() == true
753
+ clear_logs = false
754
+ end
755
+
720
756
  if allow_service_state_change?() == true && @options[:online] == true
721
- cleanup_services(true, @options[:clear_logs])
722
- elsif @options[:clear_logs] == true
723
- cleanup_services(false, @options[:clear_logs])
757
+ cleanup_services(true, clear_logs)
758
+ elsif clear_logs == true
759
+ cleanup_services(false, clear_logs)
724
760
  end
725
761
  rescue => e
726
762
  TU.exception(e)
@@ -840,6 +876,10 @@ module OfflineServicesScript
840
876
 
841
877
  @api
842
878
  end
879
+
880
+ def clear_logs_during_prepare
881
+ false
882
+ end
843
883
  end
844
884
 
845
885
  # Only require a single replication service to be OFFLINE
@@ -975,7 +1015,7 @@ module MySQLServiceScript
975
1015
  # Read the configured value for a mysql variable
976
1016
  def get_mysql_option(opt)
977
1017
  begin
978
- val = TU.cmd_result("my_print_defaults --config-file=#{@options[:my_cnf]} mysqld | grep -e'^--#{opt.gsub(/[\-\_]/, "[-_]")}'")
1018
+ val = TU.cmd_result("my_print_defaults --config-file=#{@options[:my_cnf]} mysqld | grep -e'^--#{opt.gsub(/[\-\_]/, "[-_]")}='")
979
1019
  rescue CommandError => ce
980
1020
  return nil
981
1021
  end
data/lib/tungsten/util.rb CHANGED
@@ -154,6 +154,17 @@ class TungstenUtil
154
154
  @log.puts(old_log.read())
155
155
  end
156
156
 
157
+ def limit_file_permissions(path)
158
+ if File.exists?(path)
159
+ # Get values like 0660 or 0700 for the log and umask
160
+ log_perms = sprintf("%o", File.stat(path).mode)[-4,4].to_i(8)
161
+ max_perms = sprintf("%04d", 777-sprintf("%o", File.umask()).to_i()).to_i(8)
162
+ # Calculate the target permissions for @log and set them
163
+ set_to_perms = log_perms & max_perms
164
+ File.chmod(sprintf("%o", set_to_perms).to_i(8), path)
165
+ end
166
+ end
167
+
157
168
  def reset_errors
158
169
  @num_errors = 0
159
170
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: continuent-tools-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.0
4
+ version: 0.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Continuent
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-06 00:00:00.000000000 Z
11
+ date: 2015-12-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json_pure
@@ -134,6 +134,7 @@ files:
134
134
  - lib/iniparse/lines.rb
135
135
  - lib/iniparse/parser.rb
136
136
  - lib/iniparse.rb
137
+ - lib/ipparse/platforms/darwin.rb
137
138
  - lib/ipparse/platforms/linux.rb
138
139
  - lib/ipparse/README
139
140
  - lib/ipparse.rb