backup-remote 0.0.2

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.
Files changed (135) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +112 -0
  3. data/bin/backup-remote +5 -0
  4. data/lib/backup.rb +155 -0
  5. data/lib/backup/archive.rb +170 -0
  6. data/lib/backup/binder.rb +22 -0
  7. data/lib/backup/cleaner.rb +116 -0
  8. data/lib/backup/cli.rb +374 -0
  9. data/lib/backup/cloud_io/base.rb +41 -0
  10. data/lib/backup/cloud_io/cloud_files.rb +298 -0
  11. data/lib/backup/cloud_io/s3.rb +260 -0
  12. data/lib/backup/compressor/base.rb +35 -0
  13. data/lib/backup/compressor/bzip2.rb +39 -0
  14. data/lib/backup/compressor/custom.rb +53 -0
  15. data/lib/backup/compressor/gzip.rb +74 -0
  16. data/lib/backup/config.rb +121 -0
  17. data/lib/backup/config/dsl.rb +106 -0
  18. data/lib/backup/config/helpers.rb +143 -0
  19. data/lib/backup/database/base.rb +85 -0
  20. data/lib/backup/database/mongodb.rb +187 -0
  21. data/lib/backup/database/mysql.rb +192 -0
  22. data/lib/backup/database/openldap.rb +95 -0
  23. data/lib/backup/database/postgresql.rb +133 -0
  24. data/lib/backup/database/redis.rb +179 -0
  25. data/lib/backup/database/remote_mysql.rb +248 -0
  26. data/lib/backup/database/riak.rb +82 -0
  27. data/lib/backup/database/sqlite.rb +57 -0
  28. data/lib/backup/encryptor/base.rb +29 -0
  29. data/lib/backup/encryptor/gpg.rb +747 -0
  30. data/lib/backup/encryptor/open_ssl.rb +77 -0
  31. data/lib/backup/errors.rb +58 -0
  32. data/lib/backup/logger.rb +199 -0
  33. data/lib/backup/logger/console.rb +51 -0
  34. data/lib/backup/logger/fog_adapter.rb +29 -0
  35. data/lib/backup/logger/logfile.rb +133 -0
  36. data/lib/backup/logger/syslog.rb +116 -0
  37. data/lib/backup/model.rb +479 -0
  38. data/lib/backup/notifier/base.rb +128 -0
  39. data/lib/backup/notifier/campfire.rb +63 -0
  40. data/lib/backup/notifier/command.rb +102 -0
  41. data/lib/backup/notifier/datadog.rb +107 -0
  42. data/lib/backup/notifier/flowdock.rb +103 -0
  43. data/lib/backup/notifier/hipchat.rb +118 -0
  44. data/lib/backup/notifier/http_post.rb +117 -0
  45. data/lib/backup/notifier/mail.rb +249 -0
  46. data/lib/backup/notifier/nagios.rb +69 -0
  47. data/lib/backup/notifier/pagerduty.rb +81 -0
  48. data/lib/backup/notifier/prowl.rb +68 -0
  49. data/lib/backup/notifier/pushover.rb +74 -0
  50. data/lib/backup/notifier/ses.rb +105 -0
  51. data/lib/backup/notifier/slack.rb +148 -0
  52. data/lib/backup/notifier/twitter.rb +58 -0
  53. data/lib/backup/notifier/zabbix.rb +63 -0
  54. data/lib/backup/package.rb +55 -0
  55. data/lib/backup/packager.rb +107 -0
  56. data/lib/backup/pipeline.rb +128 -0
  57. data/lib/backup/remote/command.rb +82 -0
  58. data/lib/backup/splitter.rb +76 -0
  59. data/lib/backup/storage/base.rb +69 -0
  60. data/lib/backup/storage/cloud_files.rb +158 -0
  61. data/lib/backup/storage/cycler.rb +75 -0
  62. data/lib/backup/storage/dropbox.rb +212 -0
  63. data/lib/backup/storage/ftp.rb +112 -0
  64. data/lib/backup/storage/local.rb +64 -0
  65. data/lib/backup/storage/qiniu.rb +65 -0
  66. data/lib/backup/storage/rsync.rb +248 -0
  67. data/lib/backup/storage/s3.rb +156 -0
  68. data/lib/backup/storage/scp.rb +67 -0
  69. data/lib/backup/storage/sftp.rb +82 -0
  70. data/lib/backup/syncer/base.rb +70 -0
  71. data/lib/backup/syncer/cloud/base.rb +179 -0
  72. data/lib/backup/syncer/cloud/cloud_files.rb +83 -0
  73. data/lib/backup/syncer/cloud/local_file.rb +100 -0
  74. data/lib/backup/syncer/cloud/s3.rb +110 -0
  75. data/lib/backup/syncer/rsync/base.rb +54 -0
  76. data/lib/backup/syncer/rsync/local.rb +31 -0
  77. data/lib/backup/syncer/rsync/pull.rb +51 -0
  78. data/lib/backup/syncer/rsync/push.rb +205 -0
  79. data/lib/backup/template.rb +46 -0
  80. data/lib/backup/utilities.rb +224 -0
  81. data/lib/backup/version.rb +5 -0
  82. data/templates/cli/archive +28 -0
  83. data/templates/cli/compressor/bzip2 +4 -0
  84. data/templates/cli/compressor/custom +7 -0
  85. data/templates/cli/compressor/gzip +4 -0
  86. data/templates/cli/config +123 -0
  87. data/templates/cli/databases/mongodb +15 -0
  88. data/templates/cli/databases/mysql +18 -0
  89. data/templates/cli/databases/openldap +24 -0
  90. data/templates/cli/databases/postgresql +16 -0
  91. data/templates/cli/databases/redis +16 -0
  92. data/templates/cli/databases/riak +17 -0
  93. data/templates/cli/databases/sqlite +11 -0
  94. data/templates/cli/encryptor/gpg +27 -0
  95. data/templates/cli/encryptor/openssl +9 -0
  96. data/templates/cli/model +26 -0
  97. data/templates/cli/notifier/zabbix +15 -0
  98. data/templates/cli/notifiers/campfire +12 -0
  99. data/templates/cli/notifiers/command +32 -0
  100. data/templates/cli/notifiers/datadog +57 -0
  101. data/templates/cli/notifiers/flowdock +16 -0
  102. data/templates/cli/notifiers/hipchat +16 -0
  103. data/templates/cli/notifiers/http_post +32 -0
  104. data/templates/cli/notifiers/mail +24 -0
  105. data/templates/cli/notifiers/nagios +13 -0
  106. data/templates/cli/notifiers/pagerduty +12 -0
  107. data/templates/cli/notifiers/prowl +11 -0
  108. data/templates/cli/notifiers/pushover +11 -0
  109. data/templates/cli/notifiers/ses +15 -0
  110. data/templates/cli/notifiers/slack +22 -0
  111. data/templates/cli/notifiers/twitter +13 -0
  112. data/templates/cli/splitter +7 -0
  113. data/templates/cli/storages/cloud_files +11 -0
  114. data/templates/cli/storages/dropbox +20 -0
  115. data/templates/cli/storages/ftp +13 -0
  116. data/templates/cli/storages/local +8 -0
  117. data/templates/cli/storages/qiniu +12 -0
  118. data/templates/cli/storages/rsync +17 -0
  119. data/templates/cli/storages/s3 +16 -0
  120. data/templates/cli/storages/scp +15 -0
  121. data/templates/cli/storages/sftp +15 -0
  122. data/templates/cli/syncers/cloud_files +22 -0
  123. data/templates/cli/syncers/rsync_local +20 -0
  124. data/templates/cli/syncers/rsync_pull +28 -0
  125. data/templates/cli/syncers/rsync_push +28 -0
  126. data/templates/cli/syncers/s3 +27 -0
  127. data/templates/general/links +3 -0
  128. data/templates/general/version.erb +2 -0
  129. data/templates/notifier/mail/failure.erb +16 -0
  130. data/templates/notifier/mail/success.erb +16 -0
  131. data/templates/notifier/mail/warning.erb +16 -0
  132. data/templates/storage/dropbox/authorization_url.erb +6 -0
  133. data/templates/storage/dropbox/authorized.erb +4 -0
  134. data/templates/storage/dropbox/cache_file_written.erb +10 -0
  135. metadata +1122 -0
@@ -0,0 +1,95 @@
1
+ # encoding: utf-8
2
+
3
+ module Backup
4
+ module Database
5
+ class OpenLDAP < Base
6
+ class Error < Backup::Error; end
7
+
8
+ ##
9
+ # Name of the ldap backup
10
+ attr_accessor :name
11
+
12
+ ##
13
+ # run slapcat under sudo if needed
14
+ # make sure to set SUID on a file, to let you run the file with permissions of file owner
15
+ # eg. sudo chmod u+s /usr/sbin/slapcat
16
+ attr_accessor :use_sudo
17
+
18
+ ##
19
+ # Stores the location of the slapd.conf or slapcat confdir
20
+ attr_accessor :slapcat_conf
21
+
22
+ ##
23
+ # Additional slapcat options
24
+ attr_accessor :slapcat_args
25
+
26
+ ##
27
+ # Path to slapcat utility (optional)
28
+ attr_accessor :slapcat_utility
29
+
30
+ ##
31
+ # Takes the name of the archive and the configuration block
32
+ def initialize(model, database_id = nil, &block)
33
+ super
34
+ instance_eval(&block) if block_given?
35
+
36
+ @name ||= 'ldap_backup'
37
+ @use_sudo ||= false
38
+ @slapcat_args ||= Array.new
39
+ @slapcat_utility ||= utility(:slapcat)
40
+ @slapcat_conf ||= '/etc/ldap/slapd.d'
41
+ end
42
+
43
+ ##
44
+ # Performs the slapcat command and outputs the
45
+ # data to the specified path based on the 'trigger'
46
+ def perform!
47
+ super
48
+
49
+ pipeline = Pipeline.new
50
+ dump_ext = 'ldif'
51
+
52
+ pipeline << slapcat
53
+ if @model.compressor
54
+ @model.compressor.compress_with do |command, ext|
55
+ pipeline << command
56
+ dump_ext << ext
57
+ end
58
+ end
59
+
60
+ pipeline << "#{ utility(:cat) } > " +
61
+ "'#{ File.join(dump_path, dump_filename) }.#{ dump_ext }'"
62
+
63
+ pipeline.run
64
+ if pipeline.success?
65
+ log!(:finished)
66
+ else
67
+ raise Error, "Dump Failed!\n" + pipeline.error_messages
68
+ end
69
+ end
70
+
71
+ private
72
+
73
+ ##
74
+ # Builds the full slapcat string based on all attributes
75
+ def slapcat
76
+ command = "#{ slapcat_utility } #{ slapcat_conf_option } #{ slapcat_conf } #{ user_options }"
77
+ command.prepend("sudo ") if use_sudo
78
+ command
79
+ end
80
+
81
+ ##
82
+ # Uses different slapcat switch depending on confdir or conffile set
83
+ def slapcat_conf_option
84
+ @slapcat_conf.include?(".d") ? "-F" : "-f"
85
+ end
86
+
87
+ ##
88
+ # Builds a compatible string for the additional options
89
+ # specified by the user
90
+ def user_options
91
+ slapcat_args.join(' ')
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,133 @@
1
+ # encoding: utf-8
2
+
3
+ module Backup
4
+ module Database
5
+ class PostgreSQL < Base
6
+ class Error < Backup::Error; end
7
+
8
+ ##
9
+ # Name of the database that needs to get dumped.
10
+ # To dump all databases, set this to `:all` or leave blank.
11
+ # +username+ must be a PostgreSQL superuser to run `pg_dumpall`.
12
+ attr_accessor :name
13
+
14
+ ##
15
+ # Credentials for the specified database
16
+ attr_accessor :username, :password
17
+
18
+ ##
19
+ # If set the pg_dump(all) command is executed as the given user
20
+ attr_accessor :sudo_user
21
+
22
+ ##
23
+ # Connectivity options
24
+ attr_accessor :host, :port, :socket
25
+
26
+ ##
27
+ # Tables to skip while dumping the database.
28
+ # If `name` is set to :all (or not specified), these are ignored.
29
+ attr_accessor :skip_tables
30
+
31
+ ##
32
+ # Tables to dump. This in only valid if `name` is specified.
33
+ # If none are given, the entire database will be dumped.
34
+ attr_accessor :only_tables
35
+
36
+ ##
37
+ # Additional "pg_dump" or "pg_dumpall" options
38
+ attr_accessor :additional_options
39
+
40
+ def initialize(model, database_id = nil, &block)
41
+ super
42
+ instance_eval(&block) if block_given?
43
+
44
+ @name ||= :all
45
+ end
46
+
47
+ ##
48
+ # Performs the pgdump command and outputs the dump file
49
+ # in the +dump_path+ using +dump_filename+.
50
+ #
51
+ # <trigger>/databases/PostgreSQL[-<database_id>].sql[.gz]
52
+ def perform!
53
+ super
54
+
55
+ pipeline = Pipeline.new
56
+ dump_ext = 'sql'
57
+
58
+ pipeline << (dump_all? ? pgdumpall : pgdump)
59
+
60
+ model.compressor.compress_with do |command, ext|
61
+ pipeline << command
62
+ dump_ext << ext
63
+ end if model.compressor
64
+
65
+ pipeline << "#{ utility(:cat) } > " +
66
+ "'#{ File.join(dump_path, dump_filename) }.#{ dump_ext }'"
67
+
68
+ pipeline.run
69
+ if pipeline.success?
70
+ log!(:finished)
71
+ else
72
+ raise Error, "Dump Failed!\n" + pipeline.error_messages
73
+ end
74
+ end
75
+
76
+ def pgdump
77
+ "#{ password_option }" +
78
+ "#{ sudo_option }" +
79
+ "#{ utility(:pg_dump) } #{ username_option } #{ connectivity_options } " +
80
+ "#{ user_options } #{ tables_to_dump } #{ tables_to_skip } #{ name }"
81
+ end
82
+
83
+ def pgdumpall
84
+ "#{ password_option }" +
85
+ "#{ sudo_option }" +
86
+ "#{ utility(:pg_dumpall) } #{ username_option } " +
87
+ "#{ connectivity_options } #{ user_options }"
88
+ end
89
+
90
+ def password_option
91
+ "PGPASSWORD=#{ Shellwords.escape(password) } " if password
92
+ end
93
+
94
+ def sudo_option
95
+ "#{ utility(:sudo) } -n -H -u #{ sudo_user } " if sudo_user
96
+ end
97
+
98
+ def username_option
99
+ "--username=#{ Shellwords.escape(username) }" if username
100
+ end
101
+
102
+ def connectivity_options
103
+ return "--host='#{ socket }'" if socket
104
+
105
+ opts = []
106
+ opts << "--host='#{ host }'" if host
107
+ opts << "--port='#{ port }'" if port
108
+ opts.join(' ')
109
+ end
110
+
111
+ def user_options
112
+ Array(additional_options).join(' ')
113
+ end
114
+
115
+ def tables_to_dump
116
+ Array(only_tables).map do |table|
117
+ "--table='#{ table }'"
118
+ end.join(' ')
119
+ end
120
+
121
+ def tables_to_skip
122
+ Array(skip_tables).map do |table|
123
+ "--exclude-table='#{ table }'"
124
+ end.join(' ')
125
+ end
126
+
127
+ def dump_all?
128
+ name == :all
129
+ end
130
+
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,179 @@
1
+ # encoding: utf-8
2
+
3
+ module Backup
4
+ module Database
5
+ class Redis < Base
6
+ class Error < Backup::Error; end
7
+
8
+ MODES = [:copy, :sync]
9
+
10
+ ##
11
+ # Mode of operation.
12
+ #
13
+ # [:copy]
14
+ # Copies the redis dump file specified by {#rdb_path}.
15
+ # This data will be current as of the last RDB Snapshot
16
+ # performed by the server (per your redis.conf settings).
17
+ # You may set {#invoke_save} to +true+ to have Backup issue
18
+ # a +SAVE+ command to update the dump file with the current
19
+ # data before performing the copy.
20
+ #
21
+ # [:sync]
22
+ # Performs a dump of your redis data using +redis-cli --rdb -+.
23
+ # Redis implements this internally using a +SYNC+ command.
24
+ # The operation is analogous to requesting a +BGSAVE+, then having the
25
+ # dump returned. This mode is capable of dumping data from a local or
26
+ # remote server. Requires Redis v2.6 or better.
27
+ #
28
+ # Defaults to +:copy+.
29
+ attr_accessor :mode
30
+
31
+ ##
32
+ # Full path to the redis dump file.
33
+ #
34
+ # Required when {#mode} is +:copy+.
35
+ attr_accessor :rdb_path
36
+
37
+ ##
38
+ # Perform a +SAVE+ command using the +redis-cli+ utility
39
+ # before copying the dump file specified by {#rdb_path}.
40
+ #
41
+ # Only valid when {#mode} is +:copy+.
42
+ attr_accessor :invoke_save
43
+
44
+ ##
45
+ # Connectivity options for the +redis-cli+ utility.
46
+ attr_accessor :host, :port, :socket
47
+
48
+ ##
49
+ # Password for the +redis-cli+ utility.
50
+ attr_accessor :password
51
+
52
+ ##
53
+ # Additional options for the +redis-cli+ utility.
54
+ attr_accessor :additional_options
55
+
56
+ def initialize(model, database_id = nil, &block)
57
+ super
58
+ instance_eval(&block) if block_given?
59
+
60
+ @mode ||= :copy
61
+
62
+ unless MODES.include?(mode)
63
+ raise Error, "'#{ mode }' is not a valid mode"
64
+ end
65
+
66
+ if mode == :copy && rdb_path.nil?
67
+ raise Error, '`rdb_path` must be set when `mode` is :copy'
68
+ end
69
+ end
70
+
71
+ ##
72
+ # Performs the dump based on {#mode} and stores the Redis dump file
73
+ # to the +dump_path+ using the +dump_filename+.
74
+ #
75
+ # <trigger>/databases/Redis[-<database_id>].rdb[.gz]
76
+ def perform!
77
+ super
78
+
79
+ case mode
80
+ when :sync
81
+ # messages output by `redis-cli --rdb` on $stderr
82
+ Logger.configure do
83
+ ignore_warning(/Transfer finished with success/)
84
+ ignore_warning(/SYNC sent to master/)
85
+ end
86
+ sync!
87
+ when :copy
88
+ save! if invoke_save
89
+ copy!
90
+ end
91
+
92
+ log!(:finished)
93
+ end
94
+
95
+ private
96
+
97
+ def sync!
98
+ pipeline = Pipeline.new
99
+ dump_ext = 'rdb'
100
+
101
+ pipeline << "#{ redis_cli_cmd } --rdb -"
102
+
103
+ model.compressor.compress_with do |command, ext|
104
+ pipeline << command
105
+ dump_ext << ext
106
+ end if model.compressor
107
+
108
+ pipeline << "#{ utility(:cat) } > " +
109
+ "'#{ File.join(dump_path, dump_filename) }.#{ dump_ext }'"
110
+
111
+ pipeline.run
112
+
113
+ unless pipeline.success?
114
+ raise Error, "Dump Failed!\n" + pipeline.error_messages
115
+ end
116
+ end
117
+
118
+ def save!
119
+ resp = run("#{ redis_cli_cmd } SAVE")
120
+ unless resp =~ /OK$/
121
+ raise Error, <<-EOS
122
+ Failed to invoke the `SAVE` command
123
+ Response was: #{ resp }
124
+ EOS
125
+ end
126
+
127
+ rescue Error
128
+ if resp =~ /save already in progress/
129
+ unless (attempts ||= '0').next! == '5'
130
+ sleep 5
131
+ retry
132
+ end
133
+ end
134
+ raise
135
+ end
136
+
137
+ def copy!
138
+ unless File.exist?(rdb_path)
139
+ raise Error, <<-EOS
140
+ Redis database dump not found
141
+ `rdb_path` was '#{ rdb_path }'
142
+ EOS
143
+ end
144
+
145
+ dst_path = File.join(dump_path, dump_filename + '.rdb')
146
+ if model.compressor
147
+ model.compressor.compress_with do |command, ext|
148
+ run("#{ command } -c '#{ rdb_path }' > '#{ dst_path + ext }'")
149
+ end
150
+ else
151
+ FileUtils.cp(rdb_path, dst_path)
152
+ end
153
+ end
154
+
155
+ def redis_cli_cmd
156
+ "#{ utility('redis-cli') } #{ password_option } " +
157
+ "#{ connectivity_options } #{ user_options }"
158
+ end
159
+
160
+ def password_option
161
+ "-a '#{ password }'" if password
162
+ end
163
+
164
+ def connectivity_options
165
+ return "-s '#{ socket }'" if socket
166
+
167
+ opts = []
168
+ opts << "-h '#{ host }'" if host
169
+ opts << "-p '#{ port }'" if port
170
+ opts.join(' ')
171
+ end
172
+
173
+ def user_options
174
+ Array(additional_options).join(' ')
175
+ end
176
+
177
+ end
178
+ end
179
+ end
@@ -0,0 +1,248 @@
1
+ # encoding: utf-8
2
+ require 'net/ssh'
3
+
4
+ require 'sshkit'
5
+ require 'sshkit/dsl'
6
+ require 'sshkit/sudo'
7
+
8
+
9
+ module Backup
10
+ module Database
11
+ class RemoteMySQL < Base
12
+ class Error < Backup::Error; end
13
+
14
+ include SSHKit::DSL
15
+
16
+ # server options
17
+ attr_accessor :server_host
18
+ attr_accessor :server_ssh_user
19
+ attr_accessor :server_ssh_password
20
+ attr_accessor :server_ssh_key
21
+ attr_accessor :server_backup_path
22
+
23
+
24
+ ##
25
+ # Name of the database that needs to get dumped
26
+ # To dump all databases, set this to `:all` or leave blank.
27
+ attr_accessor :name
28
+
29
+ ##
30
+ # Credentials for the specified database
31
+ attr_accessor :username, :password
32
+
33
+ ##
34
+ # Connectivity options
35
+ attr_accessor :host, :port, :socket
36
+
37
+ ##
38
+ # Tables to skip while dumping the database
39
+ #
40
+ # If `name` is set to :all (or not specified), these must include
41
+ # a database name. e.g. 'name.table'.
42
+ # If `name` is given, these may simply be table names.
43
+ attr_accessor :skip_tables
44
+
45
+ ##
46
+ # Tables to dump. This in only valid if `name` is specified.
47
+ # If none are given, the entire database will be dumped.
48
+ attr_accessor :only_tables
49
+
50
+ ##
51
+ # Additional "mysqldump" or "innobackupex (backup creation)" options
52
+ attr_accessor :additional_options
53
+
54
+ ##
55
+ # Additional innobackupex log preparation phase ("apply-logs") options
56
+ attr_accessor :prepare_options
57
+
58
+ ##
59
+ # Default is :mysqldump (which is built in MySQL and generates
60
+ # a textual SQL file), but can be changed to :innobackupex, which
61
+ # has more feasible restore times for large databases.
62
+ # See: http://www.percona.com/doc/percona-xtrabackup/
63
+ attr_accessor :backup_engine
64
+
65
+ ##
66
+ # If true (which is the default behaviour), the backup will be prepared
67
+ # after it has been successfuly created. This option is only valid if
68
+ # :backup_engine is set to :innobackupex.
69
+ attr_accessor :prepare_backup
70
+
71
+ ##
72
+ # If set the backup engine command block is executed as the given user
73
+ attr_accessor :sudo_user
74
+
75
+ ##
76
+ # If set, do not suppress innobackupdb output (useful for debugging)
77
+ attr_accessor :verbose
78
+
79
+ def initialize(model, database_id = nil, &block)
80
+ super
81
+ instance_eval(&block) if block_given?
82
+
83
+ @name ||= :all
84
+ @backup_engine ||= :mysqldump
85
+ @prepare_backup = true if @prepare_backup.nil?
86
+ end
87
+
88
+ ##
89
+ # Performs the mysqldump or innobackupex command and outputs
90
+ # the dump file in the +dump_path+ using +dump_filename+.
91
+ #
92
+ # <trigger>/databases/MySQL[-<database_id>].[sql|tar][.gz]
93
+ def perform!
94
+ super
95
+
96
+
97
+ #
98
+ pipeline = Pipeline.new
99
+ dump_ext = sql_backup? ? 'sql' : 'tar'
100
+
101
+ pipeline << sudo_option(sql_backup? ? mysqldump : innobackupex)
102
+
103
+ model.compressor.compress_with do |command, ext|
104
+ pipeline << command
105
+ dump_ext << ext
106
+ end if model.compressor
107
+
108
+ dump_remote_file = File.join('/tmp', dump_filename+"."+dump_ext)
109
+ pipeline << "#{ utility(:cat) } > '#{ dump_remote_file }'"
110
+
111
+
112
+
113
+
114
+ # generate backup on remote server
115
+ cmd_remote = pipeline.commands.join(" | ")
116
+
117
+ remote = Backup::Remote::Command.new
118
+ res_generate = remote.run_ssh_cmd(server_host, server_ssh_user, server_ssh_password, cmd_remote)
119
+
120
+ if res_generate[:res]==0
121
+ raise 'Cannot create backup on server'
122
+ end
123
+
124
+ # download backup
125
+ dump_file = File.join(dump_path, dump_filename+"."+dump_ext)
126
+
127
+ #puts "dump local: #{dump_file}"
128
+
129
+ res_download = remote.ssh_download_file(server_host, server_ssh_user, server_ssh_password, dump_remote_file, dump_file)
130
+
131
+ #puts "res: #{res_download}"
132
+
133
+ if res_download[:res]==0
134
+ raise 'Cannot download file from server'
135
+ end
136
+
137
+ #puts "pipe: #{pipeline.commands.inspect}"
138
+ #puts "cmd: #{cmd_remote}"
139
+
140
+ #exit
141
+
142
+ # download dump from server
143
+
144
+ #puts "file: #{dump_filename}"
145
+ #puts "path: #{dump_path}"
146
+
147
+ #exit
148
+
149
+ #pipeline.run
150
+ #if pipeline.success?
151
+ # log!(:finished)
152
+ #else
153
+ # raise Error, "Dump Failed!\n" + pipeline.error_messages
154
+ #end
155
+ end
156
+
157
+ private
158
+
159
+ def mysqldump
160
+ "#{ utility(:mysqldump) } #{ user_options } #{ credential_options } " +
161
+ "#{ connectivity_options } #{ name_option } " +
162
+ "#{ tables_to_dump } #{ tables_to_skip }"
163
+ end
164
+
165
+ def credential_options
166
+ opts = []
167
+ opts << "--user=#{ Shellwords.escape(username) }" if username
168
+ opts << "--password=#{ Shellwords.escape(password) }" if password
169
+ opts.join(' ')
170
+ end
171
+
172
+ def connectivity_options
173
+ return "--socket='#{ socket }'" if socket
174
+
175
+ opts = []
176
+ opts << "--host='#{ host }'" if host
177
+ opts << "--port='#{ port }'" if port
178
+ opts.join(' ')
179
+ end
180
+
181
+ def user_options
182
+ Array(additional_options).join(' ')
183
+ end
184
+
185
+ def user_prepare_options
186
+ Array(prepare_options).join(' ')
187
+ end
188
+
189
+ def name_option
190
+ dump_all? ? '--all-databases' : name
191
+ end
192
+
193
+ def tables_to_dump
194
+ Array(only_tables).join(' ') unless dump_all?
195
+ end
196
+
197
+ def tables_to_skip
198
+ Array(skip_tables).map do |table|
199
+ table = (dump_all? || table['.']) ? table : "#{ name }.#{ table }"
200
+ "--ignore-table='#{ table }'"
201
+ end.join(' ')
202
+ end
203
+
204
+ def dump_all?
205
+ name == :all
206
+ end
207
+
208
+ def sql_backup?
209
+ backup_engine.to_sym == :mysqldump
210
+ end
211
+
212
+ def innobackupex
213
+ # Creation phase
214
+ "#{ utility(:innobackupex) } #{ credential_options } " +
215
+ "#{ connectivity_options } #{ user_options } " +
216
+ "--no-timestamp #{ temp_dir } #{ quiet_option } && " +
217
+ innobackupex_prepare +
218
+ # Move files to tar-ed stream on stdout
219
+ "#{ utility(:tar) } --remove-files -cf - " +
220
+ "-C #{ File.dirname(temp_dir) } #{ File.basename(temp_dir) }"
221
+ end
222
+
223
+ def innobackupex_prepare
224
+ return "" unless @prepare_backup
225
+ # Log applying phase (prepare for restore)
226
+ "#{ utility(:innobackupex) } --apply-log #{ temp_dir } " +
227
+ "#{ user_prepare_options } #{ quiet_option } && "
228
+ end
229
+
230
+ def sudo_option(command_block)
231
+ return command_block unless sudo_user
232
+
233
+ "sudo -s -u #{ sudo_user } -- <<END_OF_SUDO\n" +
234
+ "#{command_block}\n" +
235
+ "END_OF_SUDO\n"
236
+ end
237
+
238
+ def quiet_option
239
+ verbose ? "" : " 2> /dev/null "
240
+ end
241
+
242
+ def temp_dir
243
+ File.join(dump_path, dump_filename + ".bkpdir")
244
+ end
245
+
246
+ end
247
+ end
248
+ end