flydata 0.2.22 → 0.2.23

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