flydata 0.2.22 → 0.2.23

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: 99feeb76fa109f4255e1d76c881d1631e82fdfbe
4
- data.tar.gz: 8c080c31ac049d2ad3e30bef154507a6ec15aec7
3
+ metadata.gz: b1b0c1f87ad981df879da76c17b2e4fc99246273
4
+ data.tar.gz: aa8b2361f3639d1891019339df98c84ab3f95d3d
5
5
  SHA512:
6
- metadata.gz: f51151ca084d61e1fdf9bea821151f86f54c773c53223daa35a0ac5e173125906cc2cee2ab53ef691bcebcd7f1ae59b96476977786e6d076b3542021dea982cb
7
- data.tar.gz: fbca06f1f714479abcf848e16cd9905579ed857ffbcf7a1b9b3d42895f17fb5446f7fc5e17ffa103595e25c87ac1c06e011c03449a16b9c1f4c5afc6f52968ed
6
+ metadata.gz: a7225b7a8d99fe0087f55aea9da3b1f514386b08ab47da2e100ecea32f030f9353743827b394f50ee805d37791004a0338c4992fcde9968ea9c64be7af2ea02a
7
+ data.tar.gz: ce6c3c67dc8730820ba5ebf3a9f46d8645f1dc1eb4d29dad40164015d72ddc29c49ad608fdc877b68f8ad21daac757a36bf9caa494696a00a66e2567e098a9a6
data/Gemfile CHANGED
@@ -12,6 +12,7 @@ gem "fluent-plugin-mysql-binlog", '~> 0.0', '>= 0.0.2'
12
12
  gem "mysql2", '~> 0.3', '>= 0.3.11'
13
13
  gem "slop", '~> 3.4', '>= 3.4.6'
14
14
  gem "treetop", '~> 1.5', '>= 1.5.3'
15
+ gem "sys-filesystem", '~> 1.1', '>= 1.1.3'
15
16
 
16
17
  group :development do
17
18
  gem "jeweler", '~> 1.8', '>= 1.8.8'
@@ -25,6 +25,7 @@ GEM
25
25
  diff-lcs (1.2.5)
26
26
  faraday (0.8.9)
27
27
  multipart-post (~> 1.2.0)
28
+ ffi (1.9.6)
28
29
  fluent-plugin-mysql-binlog (0.0.2)
29
30
  activesupport
30
31
  fluentd
@@ -108,6 +109,8 @@ GEM
108
109
  sigdump (0.2.2)
109
110
  slop (3.6.0)
110
111
  sqlite3 (1.3.9)
112
+ sys-filesystem (1.1.3)
113
+ ffi
111
114
  thread_safe (0.3.4)
112
115
  timecop (0.7.1)
113
116
  treetop (1.5.3)
@@ -137,5 +140,6 @@ DEPENDENCIES
137
140
  ruby-prof (~> 0.15, >= 0.15.1)
138
141
  slop (~> 3.4, >= 3.4.6)
139
142
  sqlite3 (~> 1.3, >= 1.3.9)
143
+ sys-filesystem (~> 1.1, >= 1.1.3)
140
144
  timecop (~> 0.7, >= 0.7.1)
141
145
  treetop (~> 1.5, >= 1.5.3)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.22
1
+ 0.2.23
@@ -2,14 +2,16 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
+ # stub: flydata 0.2.23 ruby lib
5
6
 
6
7
  Gem::Specification.new do |s|
7
8
  s.name = "flydata"
8
- s.version = "0.2.22"
9
+ s.version = "0.2.23"
9
10
 
10
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
+ s.require_paths = ["lib"]
11
13
  s.authors = ["Koichi Fujikawa", "Masashi Miyazaki", "Matthew Luu", "Mak Inada", "Sriram NS"]
12
- s.date = "2014-12-15"
14
+ s.date = "2014-12-17"
13
15
  s.description = "FlyData Agent"
14
16
  s.email = "sysadmin@flydata.com"
15
17
  s.executables = ["fdmysqldump", "flydata", "serverinfo"]
@@ -143,8 +145,7 @@ Gem::Specification.new do |s|
143
145
  ]
144
146
  s.homepage = "http://flydata.com/"
145
147
  s.licenses = ["All right reserved."]
146
- s.require_paths = ["lib"]
147
- s.rubygems_version = "2.0.14"
148
+ s.rubygems_version = "2.2.2"
148
149
  s.summary = "FlyData Agent"
149
150
 
150
151
  if s.respond_to? :specification_version then
@@ -162,6 +163,7 @@ Gem::Specification.new do |s|
162
163
  s.add_runtime_dependency(%q<mysql2>, [">= 0.3.11", "~> 0.3"])
163
164
  s.add_runtime_dependency(%q<slop>, [">= 3.4.6", "~> 3.4"])
164
165
  s.add_runtime_dependency(%q<treetop>, [">= 1.5.3", "~> 1.5"])
166
+ s.add_runtime_dependency(%q<sys-filesystem>, [">= 1.1.3", "~> 1.1"])
165
167
  s.add_development_dependency(%q<jeweler>, [">= 1.8.8", "~> 1.8"])
166
168
  s.add_development_dependency(%q<rspec>, ["~> 3.0"])
167
169
  s.add_development_dependency(%q<timecop>, [">= 0.7.1", "~> 0.7"])
@@ -183,6 +185,7 @@ Gem::Specification.new do |s|
183
185
  s.add_dependency(%q<mysql2>, [">= 0.3.11", "~> 0.3"])
184
186
  s.add_dependency(%q<slop>, [">= 3.4.6", "~> 3.4"])
185
187
  s.add_dependency(%q<treetop>, [">= 1.5.3", "~> 1.5"])
188
+ s.add_dependency(%q<sys-filesystem>, [">= 1.1.3", "~> 1.1"])
186
189
  s.add_dependency(%q<jeweler>, [">= 1.8.8", "~> 1.8"])
187
190
  s.add_dependency(%q<rspec>, ["~> 3.0"])
188
191
  s.add_dependency(%q<timecop>, [">= 0.7.1", "~> 0.7"])
@@ -205,6 +208,7 @@ Gem::Specification.new do |s|
205
208
  s.add_dependency(%q<mysql2>, [">= 0.3.11", "~> 0.3"])
206
209
  s.add_dependency(%q<slop>, [">= 3.4.6", "~> 3.4"])
207
210
  s.add_dependency(%q<treetop>, [">= 1.5.3", "~> 1.5"])
211
+ s.add_dependency(%q<sys-filesystem>, [">= 1.1.3", "~> 1.1"])
208
212
  s.add_dependency(%q<jeweler>, [">= 1.8.8", "~> 1.8"])
209
213
  s.add_dependency(%q<rspec>, ["~> 3.0"])
210
214
  s.add_dependency(%q<timecop>, [">= 0.7.1", "~> 0.7"])
@@ -2,6 +2,7 @@ require 'fiber'
2
2
  require 'msgpack'
3
3
  require 'open3'
4
4
  require 'mysql2'
5
+ require 'sys/filesystem'
5
6
  require 'flydata/sync_file_manager'
6
7
  require 'flydata/compatibility_check'
7
8
  require 'flydata/output/forwarder'
@@ -24,7 +25,8 @@ module Flydata
24
25
  Slop.new do
25
26
  on 'c', 'skip-cleanup', 'Skip server cleanup'
26
27
  on 'y', 'yes', 'Skip command prompt assuming yes to all questions. Use this for batch operation.'
27
- on 'd', 'dump-file', 'Dump mysqldump into a file. Use this for debugging after making sure the free space.'
28
+ on 'd', 'dump-file', 'Dump mysqldump into a file. Use this for debugging after making sure the free space.' # dummy for compatibility
29
+ on 's', 'dump-stream', 'Dump mysqldump stream instead of saving dump file. It might cause timeout error if db size is larger than 10GB.'
28
30
  on 'n', 'no-flydata-start', 'Don\'t start the flydata agent after initial sync.'
29
31
  end
30
32
  end
@@ -290,7 +292,7 @@ module Flydata
290
292
  Flydata::Command::Conf.new.copy_templates
291
293
  end
292
294
 
293
- generate_mysqldump(de, sync_fm, opts.dump_file?) do |mysqldump_io, db_bytesize|
295
+ generate_mysqldump(de, sync_fm, !opts.dump_stream?) do |mysqldump_io, db_bytesize|
294
296
  sync_fm.save_sync_info(de['mysql_data_entry_preference']['initial_sync'], de['mysql_data_entry_preference']['tables'])
295
297
  parse_mysqldump_and_send(mysqldump_io, dp, de, sync_fm, db_bytesize)
296
298
  end
@@ -341,10 +343,22 @@ EOM
341
343
  log_info confirmation_text.strip
342
344
 
343
345
  if ask_yes_no('Start Sync?')
344
- log_info_stdout("Checking database size(not same as mysqldump data size)...")
346
+ log_info_stdout("Checking database size...")
345
347
 
346
348
  db_bytesize = Flydata::Parser::Mysql::DatabaseSizeCheck.new(de['mysql_data_entry_preference']).get_db_bytesize
347
349
  log_info_stdout(" -> #{as_size(db_bytesize)} (#{db_bytesize} byte)")
350
+
351
+ # check free disk space
352
+ free_disk_bytesize = free_disk_space(File.dirname(fp))
353
+ if (free_disk_bytesize - db_bytesize) < (1024 * 1024 * 1024) # 1GB
354
+ log_warn_stderr("!!WARNING There may not be enough disk space for a DB dump. We recommend 1GB free disk space after the dump. free disk space:#{as_size(free_disk_bytesize)}(#{free_disk_bytesize} byte) /" +
355
+ " db size:#{as_size(db_bytesize)}(#{db_bytesize} byte)")
356
+ unless ask_yes_no('Do you want to continue?')
357
+ log_warn_stderr("To change the dump file directory, delete '#' and modify the path of 'mysqldump_dir:' in '#{Preference::DataEntryPreference.conf_path(de)}'")
358
+ exit 1
359
+ end
360
+ end
361
+
348
362
  log_info_stdout("Exporting data from database.")
349
363
  log_info_stdout("This process can take hours depending on data size and load on your database. Please be patient...")
350
364
  Flydata::MysqlCompatibilityCheck.new(dp, de['mysql_data_entry_preference'], fp).check
@@ -362,6 +376,12 @@ EOM
362
376
  end
363
377
  end
364
378
 
379
+ # return available disk size(byte)
380
+ def free_disk_space(dump_path)
381
+ stat = Sys::Filesystem.stat(dump_path)
382
+ stat.block_size * stat.blocks_available
383
+ end
384
+
365
385
  def call_block_or_return_io(fp, &block)
366
386
  if block
367
387
  f_io = open_file_io(fp)
@@ -75,6 +75,7 @@ module Flydata
75
75
  end
76
76
 
77
77
  SELECT_QUERY_TMPLT = "SELECT %s"
78
+ BINLOG_RETENTION_HOURS = 24
78
79
 
79
80
  #def initialize(de_hash, dump_dir=nil)
80
81
  def initialize(dp_hash, de_hash, options={})
@@ -169,6 +170,19 @@ module Flydata
169
170
  end
170
171
  end
171
172
 
173
+ def check_mysql_binlog_retention
174
+ client = Mysql2::Client.new(@db_opts)
175
+ begin
176
+ if is_rds?(@db_opts[:host])
177
+ run_rds_retention_check(client)
178
+ else
179
+ run_mysql_retention_check(client)
180
+ end
181
+ ensure
182
+ client.close
183
+ end
184
+ end
185
+
172
186
  def check_writing_permissions
173
187
  write_errors = []
174
188
  paths_to_check = ["~/.flydata"]
@@ -183,6 +197,48 @@ module Flydata
183
197
  raise MysqlCompatibilityError, "We cannot access the directories: #{error_dir}"
184
198
  end
185
199
  end
200
+
201
+ def run_mysql_retention_check(mysql_client)
202
+ expire_logs_days_limit = BINLOG_RETENTION_HOURS / 24
203
+ sel_query = SELECT_QUERY_TMPLT % '@@expire_logs_days'
204
+ result = mysql_client.query(sel_query)
205
+ if result.first["@@expire_logs_days"]!=0 and result.first["@@expire_logs_days"] <= expire_logs_days_limit
206
+ raise MysqlCompatibilityError, "Binary log retention is too short\n " +
207
+ " We recommend the system variable '@@expire_logs_days' to be either set to 0 or at least #{expire_logs_days_limit} days"
208
+ end
209
+ end
210
+
211
+ def run_rds_retention_check(mysql_client)
212
+ sql_query = "call mysql.rds_show_configuration;"
213
+
214
+ begin
215
+ result = mysql_client.query(sql_query)
216
+ if result.first["name"]=="binlog retention hours"
217
+ if result.first["value"].nil? or result.first["value"].to_i <= BINLOG_RETENTION_HOURS
218
+ raise MysqlCompatibilityError, "Binary log retention is too short\n" +
219
+ " We recommend setting RDS binlog retention to be at least #{BINLOG_RETENTION_HOURS} hours. To do this, run this on your RDS MySQL database:\n" +
220
+ " $> call mysql.rds_set_configuration('binlog retention hours', 94);"
221
+ end
222
+ end
223
+ rescue Mysql2::Error => e
224
+ if e.message =~ /command denied to user/
225
+ log_warn_stderr("[WARNING]Cannot verify RDS retention period on currend MySQL user account.\n" +
226
+ "To see retention period, please run this on your RDS:\n" +
227
+ " $> call mysql.rds_show_configuration;\n" +
228
+ "Please verify that the hours is not nil and is at least #{BINLOG_RETENTION_HOURS} hours\n" +
229
+ "To set binlog retention hours, you can run this on your RDS:\n" +
230
+ " $> call mysql.rds_set_configuration('binlog retention hours', #{BINLOG_RETENTION_HOURS});\n"
231
+ )
232
+ else
233
+ raise e
234
+ end
235
+ end
236
+
237
+ end
238
+
239
+ def is_rds?(hostname)
240
+ hostname.match(/rds.amazonaws.com$/) != nil
241
+ end
186
242
  end
187
243
 
188
244
  end
@@ -33,4 +33,111 @@ module Flydata
33
33
  end
34
34
  end
35
35
  end
36
+
37
+ describe MysqlCompatibilityCheck do
38
+ let(:default_mysql_cred) do
39
+ {
40
+ "host" => "test",
41
+ "port" => 1234,
42
+ "username" => "test",
43
+ "password" => "password",
44
+ "database" => "test_db"
45
+ }
46
+ end
47
+ describe "#check_mysql_binlog_retention" do
48
+ context "on on-premise mysql server" do
49
+ subject { MysqlCompatibilityCheck.new({},:default_mysql_cred) }
50
+ context "where retention is below limit" do
51
+ let(:client) { double('client') }
52
+ before do
53
+ allow(Mysql2::Client).to receive(:new).and_return(client)
54
+ allow(client).to receive(:query).and_return([{"@@expire_logs_days"=>1}])
55
+ allow(client).to receive(:close)
56
+ allow(subject).to receive(:is_rds?).and_return(false)
57
+ end
58
+ it do
59
+ expect{subject.check_mysql_binlog_retention}.to raise_error(Flydata::MysqlCompatibilityCheck::MysqlCompatibilityError, /expire_logs_days/)
60
+ end
61
+ end
62
+ context "where retention is 0" do
63
+ let(:client) { double('client') }
64
+ before do
65
+ allow(Mysql2::Client).to receive(:new).and_return(client)
66
+ allow(client).to receive(:query).and_return([{"@@expire_logs_days"=>0}])
67
+ allow(subject).to receive(:is_rds?).and_return(false)
68
+ end
69
+ it do
70
+ expect{subject.check_mysql_binlog_retention}
71
+ end
72
+ end
73
+ context "where retention is above limit" do
74
+ let(:client) { double('client') }
75
+ before do
76
+ allow(Mysql2::Client).to receive(:new).and_return(client)
77
+ allow(client).to receive(:query).and_return([{"@@expire_logs_days"=>11}])
78
+ allow(subject).to receive(:is_rds?).and_return(false)
79
+ end
80
+ it do
81
+ expect{subject.check_mysql_binlog_retention}
82
+ end
83
+ end
84
+ end
85
+ context "on RDS" do
86
+ subject { MysqlCompatibilityCheck.new({},:default_mysql_cred) }
87
+ context "where retention period is nil" do
88
+ let(:client) { double('client') }
89
+ before do
90
+ allow(Mysql2::Client).to receive(:new).and_return(client)
91
+ allow(client).to receive(:query).with("SELECT @@expire_logs_days").and_return([{"@@expire_logs_days"=>0}])
92
+ allow(client).to receive(:query).with("call mysql.rds_show_configuration;").and_return([{"name"=>"binlog retention hours", "value"=>nil}])
93
+ allow(client).to receive(:close)
94
+ allow(subject).to receive(:is_rds?).and_return(true)
95
+ end
96
+ it do
97
+ expect{subject.check_mysql_binlog_retention}.to raise_error(Flydata::MysqlCompatibilityCheck::MysqlCompatibilityError, /rds_set_config/)
98
+ end
99
+ end
100
+ context "where retention period is too low" do
101
+ let(:client) { double('client') }
102
+ before do
103
+ allow(Mysql2::Client).to receive(:new).and_return(client)
104
+ allow(client).to receive(:query).with("SELECT @@expire_logs_days").and_return([{"@@expire_logs_days"=>0}])
105
+ allow(client).to receive(:query).with("call mysql.rds_show_configuration;").and_return([{"name"=>"binlog retention hours", "value"=>4}])
106
+ allow(client).to receive(:close)
107
+ allow(subject).to receive(:is_rds?).and_return(true)
108
+ end
109
+ it do
110
+ expect{subject.check_mysql_binlog_retention}.to raise_error(Flydata::MysqlCompatibilityCheck::MysqlCompatibilityError, /rds_set_config/)
111
+ end
112
+ end
113
+ context "where retention period is over recommended limit" do
114
+ let(:client) { double('client') }
115
+ before do
116
+ allow(Mysql2::Client).to receive(:new).and_return(client)
117
+ allow(client).to receive(:query).with("SELECT @@expire_logs_days").and_return([{"@@expire_logs_days"=>0}])
118
+ allow(client).to receive(:query).with("call mysql.rds_show_configuration;").and_return([{"name"=>"binlog retention hours", "value"=>120}])
119
+ allow(client).to receive(:close)
120
+ allow(subject).to receive(:is_rds?).and_return(true)
121
+ end
122
+ it do
123
+ expect{subject.check_mysql_binlog_retention}
124
+ end
125
+ end
126
+ context "where user has no access to rds configuration" do
127
+ let(:client) { double('client') }
128
+ before do
129
+ allow(Mysql2::Client).to receive(:new).and_return(client)
130
+ allow(client).to receive(:query).with("SELECT @@expire_logs_days").and_return([{"@@expire_logs_days"=>0}])
131
+ allow(client).to receive(:query).with("call mysql.rds_show_configuration;").and_raise(Mysql2::Error, "execute command denied to user")
132
+ allow(client).to receive(:close)
133
+ allow(subject).to receive(:is_rds?).and_return(true)
134
+ end
135
+ it do
136
+ expect{subject.check_mysql_binlog_retention}
137
+ end
138
+ end
139
+ end
140
+ end
141
+ end
142
+
36
143
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flydata
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.22
4
+ version: 0.2.23
5
5
  platform: ruby
6
6
  authors:
7
7
  - Koichi Fujikawa
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2014-12-15 00:00:00.000000000 Z
15
+ date: 2014-12-17 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: rest-client
@@ -222,6 +222,26 @@ dependencies:
222
222
  - - ~>
223
223
  - !ruby/object:Gem::Version
224
224
  version: '1.5'
225
+ - !ruby/object:Gem::Dependency
226
+ name: sys-filesystem
227
+ requirement: !ruby/object:Gem::Requirement
228
+ requirements:
229
+ - - '>='
230
+ - !ruby/object:Gem::Version
231
+ version: 1.1.3
232
+ - - ~>
233
+ - !ruby/object:Gem::Version
234
+ version: '1.1'
235
+ type: :runtime
236
+ prerelease: false
237
+ version_requirements: !ruby/object:Gem::Requirement
238
+ requirements:
239
+ - - '>='
240
+ - !ruby/object:Gem::Version
241
+ version: 1.1.3
242
+ - - ~>
243
+ - !ruby/object:Gem::Version
244
+ version: '1.1'
225
245
  - !ruby/object:Gem::Dependency
226
246
  name: jeweler
227
247
  requirement: !ruby/object:Gem::Requirement
@@ -545,7 +565,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
545
565
  version: '0'
546
566
  requirements: []
547
567
  rubyforge_project:
548
- rubygems_version: 2.0.14
568
+ rubygems_version: 2.2.2
549
569
  signing_key:
550
570
  specification_version: 4
551
571
  summary: FlyData Agent