continuent-tools-core 0.1.0 → 0.1.5

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: 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