continuent-tools-core 0.1.0 → 0.1.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e6e054000eca097227028c7e1207f5b974776e7c
4
- data.tar.gz: 741e8405afad6f6e8c437f4c257a90409a9fea9c
3
+ metadata.gz: 16efacbae7473d06eb2d66b15dc36930640ec849
4
+ data.tar.gz: 59927a7e2be2982ec8723e775d4314faed5ded72
5
5
  SHA512:
6
- metadata.gz: e629c48d5bdd89d9f746cb72ad0aa74d94b4d55a9d2ce1b6aacabfb2e1f877e829fd58ef513cf8d5c8e1a2f4f0e21280a2a7d6bab4f975e47c2e57e63b81729e
7
- data.tar.gz: 64e88a15d565b05ca1d30c30bf58e8e60122da6b55ae7758379e8ab0cb6ec7c0aecbf087ebcb23bc71804838a5f4a5a677743b679aff449ac143ea1f4b8b9678
6
+ metadata.gz: 6c570c00e9dbaae8194c97981266a5e5e44183539e1c6a581f58ecc48fe195526db46b524fef3ac3472c1a1929ac3fd6bef5eb3a5f7b06bd4c0409c5bb1fd072
7
+ data.tar.gz: f84cc97f36b4df6d4bfcd1c01997a52f6185a12d7b6e5cd8860d1a05c2ce4b633f72717fb2376b71e84fe714ac5f420e6f513404fce77db77e98a5d28a34c46c
@@ -0,0 +1,180 @@
1
+ #!/usr/bin/env ruby
2
+ # Copyright (C) 2014 Continuent, Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may
5
+ # not use this file except in compliance with the License. You may obtain
6
+ # 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, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations
14
+ # under the License.
15
+ #
16
+ # Initial developer(s): Jeff Mace
17
+ # Contributor(s):
18
+
19
+ begin
20
+ require 'rubygems'
21
+ gem 'continuent-tools-core'
22
+ rescue LoadError
23
+ end
24
+
25
+ require 'continuent-tools-core'
26
+
27
+ class ContinuentCreateLoad
28
+ include TungstenScript
29
+ include MySQLServiceScript
30
+ private
31
+
32
+ @@interrupted = false
33
+
34
+ def main
35
+ old_trap = trap("INT") {
36
+ ContinuentCreateLoad.interrupted?(true);
37
+ }
38
+
39
+ # Create the schema we will load data into using the local connection
40
+ TU.cmd(get_mysql_command(), false, method(:initialize_schema), nil, method(:forward_mysql_errors))
41
+ sleep 2
42
+
43
+ # Create a list of all load generation threads that should be started
44
+ load_threads = []
45
+ opt(:hosts).each{
46
+ |host|
47
+ i = 0
48
+ while (i < opt(:threads).to_i())
49
+ load_threads << {:host => host}
50
+ i = i+1
51
+ end
52
+ }
53
+ # Spin up an independent thread for each configuration of the load
54
+ # generation thread.
55
+ load_threads.peach{
56
+ |load_thread|
57
+ TU.cmd(get_mysql_command() + " -h#{load_thread[:host]}", true, method(:create_schema_load), nil, method(:forward_mysql_errors))
58
+ }
59
+
60
+ puts("\n")
61
+ trap("INT", old_trap);
62
+ end
63
+
64
+ def initialize_schema(stdin)
65
+ [
66
+ "DROP SCHEMA IF EXISTS tungsten_create_load;",
67
+ "CREATE SCHEMA tungsten_create_load;",
68
+ "CREATE TABLE tungsten_create_load.values (id int NOT NULL auto_increment primary key, val int NOT NULL, origin varchar(32) NULL);"
69
+ ].each{|sql|
70
+ stdin.puts(sql)
71
+ putc '.'
72
+ $stdout.flush()
73
+ }
74
+ end
75
+
76
+ def create_schema_load(stdin)
77
+ sql = "INSERT INTO tungsten_create_load.values (val, origin) VALUES (5, @@hostname);"
78
+ while (ContinuentCreateLoad.interrupted?() == false)
79
+ stdin.puts(sql)
80
+ putc '.'
81
+ $stdout.flush()
82
+ sleep opt(:sleep).to_i()
83
+ end
84
+ end
85
+
86
+ def forward_mysql_errors(msg)
87
+ TU.error(msg)
88
+ end
89
+
90
+ def configure
91
+ super()
92
+
93
+ add_option(:hosts, {
94
+ :on => "--hosts String",
95
+ :help => "Coordinate load generation on these servers in addition to the current host",
96
+ })
97
+
98
+ add_option(:threads, {
99
+ :on => "--threads String",
100
+ :parse => method(:parse_integer_option),
101
+ :help => "How many parallel threads should be used to generate load",
102
+ :default => 1,
103
+ })
104
+
105
+ add_option(:sleep, {
106
+ :on => "--sleep String",
107
+ :parse => method(:parse_integer_option),
108
+ :help => "How many seconds to wait between load transactions",
109
+ :default => 1,
110
+ })
111
+
112
+ add_option(:use_connector, {
113
+ :on => "--use-connector String",
114
+ :parse => method(:parse_boolean_option),
115
+ :help => "Enable/Disable use of the Tungsten Connector for adding load to the system.",
116
+ })
117
+ end
118
+
119
+ def validate
120
+ super()
121
+
122
+ unless TU.is_valid?()
123
+ return TU.is_valid?()
124
+ end
125
+
126
+ if opt(:use_connector) == nil
127
+ if TI.is_connector?()
128
+ opt(:use_connector, true)
129
+
130
+ unless TI.is_running?("connector")
131
+ TU.error("The Tungsten Connector is not running")
132
+ end
133
+
134
+ defaults_file = Tempfile.new("tungsten_nagios_connector")
135
+ opt(:my_cnf, defaults_file.path())
136
+
137
+ defaults_file.puts("[client]")
138
+ defaults_file.puts("user=#{TI.setting(TI.setting_key(CONNECTORS, "connector_user"))}")
139
+ defaults_file.puts("password=#{TI.setting(TI.setting_key(CONNECTORS, "connector_password"))}")
140
+ defaults_file.flush()
141
+
142
+ opt(:mysqlport, TI.setting(TI.setting_key(CONNECTORS, "connector_listen_port")))
143
+ opt(:mysqlhost, TI.hostname())
144
+ elsif TI.is_replicator?()
145
+ opt(:use_connector, false)
146
+
147
+ if TI.setting(TI.setting_key(REPL_SERVICES, @options[:service], "repl_datasource_type")) != "mysql"
148
+ TU.error("Unable to create load on this system because it is not configured for MySQL")
149
+ end
150
+ else
151
+ TU.error("Unable to create load on this system because it is not configured as a Tungsten Connector or Tungsten Replicator")
152
+ end
153
+ end
154
+
155
+ if opt(:hosts) != nil
156
+ hosts = opt(:hosts).split(",").uniq().delete_if{
157
+ |h|
158
+ (h == TI.hostname())
159
+ }
160
+ hosts << TI.hostname()
161
+ opt(:hosts, hosts)
162
+ else
163
+ opt(:hosts, [TI.hostname()])
164
+ end
165
+ end
166
+
167
+ def script_name
168
+ "tungsten_create_load"
169
+ end
170
+
171
+ def self.interrupted?(val = nil)
172
+ if val != nil
173
+ @@interrupted = val
174
+ end
175
+
176
+ (@@interrupted == true)
177
+ end
178
+
179
+ self.new().run()
180
+ end
@@ -38,6 +38,101 @@ class TungstenUtil
38
38
  forward_cmd_results?(original_fwd_state)
39
39
  end
40
40
  end
41
+
42
+ # A wrapper for running another Tungsten script on a remote host. This will
43
+ # automatically forward messages to the console and add any TungstenScript
44
+ # options to the command.
45
+ def tungsten_ssh_result(command, host, user)
46
+ original_fwd_state = forward_cmd_results?()
47
+ begin
48
+ if TI
49
+ prefix = "export CONTINUENT_ROOT=#{TI.root()}; "
50
+ else
51
+ prefix = ""
52
+ end
53
+
54
+ forward_cmd_results?(true)
55
+ return ssh_result("#{prefix}#{command} #{get_tungsten_command_options()}", host, user)
56
+ ensure
57
+ forward_cmd_results?(original_fwd_state)
58
+ end
59
+ end
60
+
61
+ # Run the {command} and return a string of STDOUT
62
+ def cmd(command, ignore_fail = false, stdin_method = nil, stdout_method = nil, stderr_method = nil)
63
+ errors = ""
64
+ result = ""
65
+ threads = []
66
+
67
+ debug("Execute `#{command}`")
68
+ status = Open4::popen4("export LANG=en_US; #{command}") do |pid, stdin, stdout, stderr|
69
+ if stdin_method != nil
70
+ threads << Thread.new{
71
+ stdin_method.call(stdin)
72
+ stdin.close
73
+ }
74
+ else
75
+ stdin.close
76
+ end
77
+
78
+ threads << Thread.new{
79
+ while data = stdout.gets()
80
+ if data.to_s() != ""
81
+ result+=data
82
+
83
+ if data != "" && forward_cmd_results?()
84
+ write(data, (parse_log_level(data) || get_forward_log_level()), nil, false)
85
+ end
86
+
87
+ if stdout_method != nil
88
+ stdout_method.call(data)
89
+ end
90
+ end
91
+ end
92
+ }
93
+ threads << Thread.new{
94
+ while edata = stderr.gets()
95
+ if edata.to_s() != ""
96
+ errors+=edata
97
+
98
+ if edata != "" && forward_cmd_results?()
99
+ write(edata, (parse_log_level(edata) || get_forward_log_level()), nil, false)
100
+ end
101
+
102
+ if stderr_method != nil
103
+ stderr_method.call(edata)
104
+ end
105
+ end
106
+ end
107
+ }
108
+
109
+ threads.each{|t| t.join() }
110
+ end
111
+
112
+ result.strip!()
113
+ errors.strip!()
114
+
115
+ original_errors = errors
116
+ rc = status.exitstatus
117
+ if errors == ""
118
+ errors = "No Errors"
119
+ else
120
+ errors = "Errors: #{errors}"
121
+ end
122
+
123
+ if log_cmd_results?()
124
+ debug("RC: #{rc}, Result: #{result}, #{errors}")
125
+ elsif forward_cmd_results?()
126
+ debug("RC: #{rc}, Result length #{result.length}, Errors length #{original_errors.length}")
127
+ else
128
+ debug("RC: #{rc}, Result length #{result.length}, #{errors}")
129
+ end
130
+ if rc != 0 && ! ignore_fail
131
+ raise CommandError.new(command, rc, result, original_errors)
132
+ end
133
+
134
+ return result
135
+ end
41
136
  end
42
137
 
43
138
  module TungstenScript
@@ -57,4 +152,21 @@ module TungstenScript
57
152
  end
58
153
  }
59
154
  end
155
+ end
156
+
157
+ class Array
158
+ def peach(&block)
159
+ pids = []
160
+ results = []
161
+ idx = 0
162
+
163
+ self.each{
164
+ |i|
165
+ pids[idx] = fork {
166
+ block.call(i)
167
+ }
168
+ idx = idx+1
169
+ }
170
+ pids.each{|pid| Process.waitpid(pid) }
171
+ end
60
172
  end
data/lib/tungsten/exec.rb CHANGED
@@ -238,19 +238,6 @@ class TungstenUtil
238
238
 
239
239
  return
240
240
  end
241
-
242
- # A wrapper for running another Tungsten script. This will automatically
243
- # forward messages to the console and add any TungstenScript options to
244
- # the command.
245
- def tungsten_cmd_result(command)
246
- original_fwd_state = forward_cmd_results?()
247
- begin
248
- forward_cmd_results?(true)
249
- return cmd_result("#{command} #{get_tungsten_command_options()}")
250
- ensure
251
- forward_cmd_results?(original_fwd_state)
252
- end
253
- end
254
241
 
255
242
  # Run a standard check to see if SSH connectivity to the host works
256
243
  def test_ssh(host, user)
@@ -411,6 +398,11 @@ class TungstenUtil
411
398
  |k,v|
412
399
  opts << "--net-ssh-option=#{k.to_s()}=#{v}"
413
400
  }
401
+
402
+ if @force == true
403
+ opts << "--force"
404
+ end
405
+
414
406
  return opts.join(" ")
415
407
  end
416
408
 
@@ -118,12 +118,6 @@ module TungstenScript
118
118
  :help => "Only run the script validation"
119
119
  })
120
120
 
121
- add_option(:force, {
122
- :on => "--force",
123
- :default => false,
124
- :help => "Continue operation even if script validation fails"
125
- })
126
-
127
121
  add_option(:autocomplete, {
128
122
  :on => "--autocomplete",
129
123
  :default => false,
data/lib/tungsten/util.rb CHANGED
@@ -10,6 +10,7 @@ class TungstenUtil
10
10
  @ssh_options = {}
11
11
  @display_help = false
12
12
  @num_errors = 0
13
+ @force = false
13
14
  @json_interface = false
14
15
  @json_message_cache = []
15
16
 
@@ -47,6 +48,7 @@ class TungstenUtil
47
48
  }
48
49
 
49
50
  opts=OptionParser.new
51
+ opts.on("-f", "--force") {@force = true}
50
52
  opts.on("-i", "--info") {@logger_threshold = Logger::INFO}
51
53
  opts.on("-n", "--notice") {@logger_threshold = Logger::NOTICE}
52
54
  opts.on("-q", "--quiet") {@logger_threshold = Logger::WARN}
@@ -155,8 +157,12 @@ class TungstenUtil
155
157
  @num_errors = 0
156
158
  end
157
159
 
160
+ def force?
161
+ @force
162
+ end
163
+
158
164
  def is_valid?
159
- (@num_errors == 0)
165
+ (@num_errors == 0 || @force == true)
160
166
  end
161
167
 
162
168
  def write(content="", level=Logger::INFO, hostname = nil, add_prefix = true)
@@ -168,10 +174,6 @@ class TungstenUtil
168
174
  return
169
175
  end
170
176
 
171
- unless content == "" || level == nil || add_prefix == false
172
- content = "#{get_log_level_prefix(level, hostname)}#{content}"
173
- end
174
-
175
177
  # Attempt to determine the level for this message based on it's content
176
178
  # If it is forwarded from another Tungsten script it will have a prefix
177
179
  # so we know to use stdout or stderr
@@ -181,6 +183,14 @@ class TungstenUtil
181
183
 
182
184
  if level == Logger::ERROR
183
185
  @num_errors = @num_errors + 1
186
+
187
+ if force?()
188
+ level = Logger::WARN
189
+ end
190
+ end
191
+
192
+ unless content == "" || level == nil || add_prefix == false
193
+ content = "#{get_log_level_prefix(level, hostname)}#{content}"
184
194
  end
185
195
 
186
196
  log(content)
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.1.0
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Continuent
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-05 00:00:00.000000000 Z
11
+ date: 2014-04-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json_pure
@@ -110,10 +110,12 @@ dependencies:
110
110
  version: '0'
111
111
  description:
112
112
  email: info@continuent.com
113
- executables: []
113
+ executables:
114
+ - tungsten_create_load
114
115
  extensions: []
115
116
  extra_rdoc_files: []
116
117
  files:
118
+ - bin/tungsten_create_load
117
119
  - lib/continuent-tools-core.rb
118
120
  - lib/tungsten/api.rb
119
121
  - lib/tungsten/common.rb