dmitryv-backup 2.4.0

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 (59) hide show
  1. data/CHANGELOG +125 -0
  2. data/LICENSE +20 -0
  3. data/README.md +180 -0
  4. data/VERSION +1 -0
  5. data/bin/backup +108 -0
  6. data/generators/backup/backup_generator.rb +69 -0
  7. data/generators/backup/templates/backup.rake +56 -0
  8. data/generators/backup/templates/backup.rb +229 -0
  9. data/generators/backup/templates/create_backup_tables.rb +18 -0
  10. data/generators/backup_update/backup_update_generator.rb +50 -0
  11. data/generators/backup_update/templates/migrations/update_backup_tables.rb +27 -0
  12. data/lib/backup.rb +131 -0
  13. data/lib/backup/adapters/archive.rb +34 -0
  14. data/lib/backup/adapters/base.rb +138 -0
  15. data/lib/backup/adapters/custom.rb +41 -0
  16. data/lib/backup/adapters/mysql.rb +60 -0
  17. data/lib/backup/adapters/postgresql.rb +56 -0
  18. data/lib/backup/adapters/sqlite.rb +25 -0
  19. data/lib/backup/command_helper.rb +11 -0
  20. data/lib/backup/compressors/base.rb +7 -0
  21. data/lib/backup/compressors/gzip.rb +9 -0
  22. data/lib/backup/compressors/seven_zip.rb +9 -0
  23. data/lib/backup/configuration/adapter.rb +21 -0
  24. data/lib/backup/configuration/adapter_options.rb +8 -0
  25. data/lib/backup/configuration/attributes.rb +19 -0
  26. data/lib/backup/configuration/base.rb +77 -0
  27. data/lib/backup/configuration/helpers.rb +24 -0
  28. data/lib/backup/configuration/mail.rb +20 -0
  29. data/lib/backup/configuration/smtp.rb +8 -0
  30. data/lib/backup/configuration/storage.rb +8 -0
  31. data/lib/backup/connection/cloudfiles.rb +75 -0
  32. data/lib/backup/connection/s3.rb +85 -0
  33. data/lib/backup/environment/base.rb +12 -0
  34. data/lib/backup/environment/rails_configuration.rb +15 -0
  35. data/lib/backup/environment/unix_configuration.rb +109 -0
  36. data/lib/backup/mail/base.rb +97 -0
  37. data/lib/backup/mail/mail.txt +7 -0
  38. data/lib/backup/record/base.rb +65 -0
  39. data/lib/backup/record/cloudfiles.rb +28 -0
  40. data/lib/backup/record/ftp.rb +39 -0
  41. data/lib/backup/record/local.rb +26 -0
  42. data/lib/backup/record/s3.rb +26 -0
  43. data/lib/backup/record/scp.rb +33 -0
  44. data/lib/backup/record/sftp.rb +38 -0
  45. data/lib/backup/storage/base.rb +10 -0
  46. data/lib/backup/storage/cloudfiles.rb +16 -0
  47. data/lib/backup/storage/ftp.rb +38 -0
  48. data/lib/backup/storage/local.rb +22 -0
  49. data/lib/backup/storage/s3.rb +17 -0
  50. data/lib/backup/storage/scp.rb +30 -0
  51. data/lib/backup/storage/sftp.rb +31 -0
  52. data/lib/generators/backup/USAGE +10 -0
  53. data/lib/generators/backup/backup_generator.rb +47 -0
  54. data/lib/generators/backup/templates/backup.rake +56 -0
  55. data/lib/generators/backup/templates/backup.rb +229 -0
  56. data/lib/generators/backup/templates/create_backup_tables.rb +18 -0
  57. data/setup/backup.rb +231 -0
  58. data/setup/backup.sqlite3 +0 -0
  59. metadata +271 -0
@@ -0,0 +1,7 @@
1
+ A backup was successfully created for the trigger: ":trigger"!
2
+
3
+ The backup was created on ":day of :month :year at :time", using the ":adapter" adapter.
4
+
5
+ The Backup was stored in ":location" :remote.
6
+
7
+ The following backup was stored: ":backup"
@@ -0,0 +1,65 @@
1
+ module Backup
2
+ module Record
3
+ class Base < ActiveRecord::Base
4
+
5
+ if DB_CONNECTION_SETTINGS
6
+ establish_connection(DB_CONNECTION_SETTINGS)
7
+ end
8
+
9
+ set_table_name 'backup'
10
+
11
+ default_scope :order => 'created_at desc'
12
+
13
+ # Callbacks
14
+ after_save :clean_backups
15
+
16
+ # Attributes
17
+ attr_accessor :adapter_config, :keep_backups
18
+
19
+ # Receives the options hash and stores it
20
+ def load_adapter(adapter)
21
+ self.adapter_config = adapter
22
+ self.trigger = adapter.procedure.trigger
23
+ self.adapter = adapter.procedure.adapter_name.to_s
24
+ self.filename = adapter.final_file
25
+ self.keep_backups = adapter.procedure.attributes['keep_backups']
26
+
27
+ # TODO calculate md5sum of file
28
+ load_specific_settings(adapter) if respond_to?(:load_specific_settings)
29
+ end
30
+
31
+ # Destroys all backups for the specified trigger from Remote Server (FTP)
32
+ def self.destroy_all_backups(procedure, trigger)
33
+ backups = self.all(:conditions => {:trigger => trigger})
34
+ unless backups.empty?
35
+ # Derived classes must implement this method!
36
+ self.destroy_backups(procedure, backups)
37
+
38
+ puts "\nAll \"#{procedure.trigger}\" backups destroyed.\n\n"
39
+ end
40
+ end
41
+
42
+ private
43
+
44
+ # Maintains the backup file amount on the remote server
45
+ # This is invoked after a successful record save
46
+ # This deletes the oldest files when the backup limit has been exceeded
47
+ def clean_backups
48
+ if keep_backups.is_a?(Integer)
49
+ backups = self.class.all(:conditions => {:trigger => trigger})
50
+ backups_to_destroy = backups[keep_backups, backups.size] || []
51
+
52
+ unless backups_to_destroy.empty?
53
+ # Derived classes must implement this method!
54
+ self.class.destroy_backups(adapter_config.procedure, backups_to_destroy)
55
+
56
+ puts "\nBackup storage for \"#{trigger}\" is limited to #{keep_backups} backups."
57
+ puts "\nThe #{keep_backups} most recent backups are now stored on the remote server.\n\n"
58
+ end
59
+ end
60
+ end
61
+
62
+ end
63
+ end
64
+ end
65
+
@@ -0,0 +1,28 @@
1
+ require 'backup/connection/cloudfiles'
2
+
3
+ module Backup
4
+ module Record
5
+ class CloudFiles < Backup::Record::Base
6
+
7
+ alias_attribute :container, :bucket
8
+
9
+ def load_specific_settings(adapter)
10
+ self.container = adapter.procedure.get_storage_configuration.attributes['container']
11
+ end
12
+
13
+ private
14
+
15
+ def self.destroy_backups(procedure, backups)
16
+ cf = Backup::Connection::CloudFiles.new
17
+ cf.static_initialize(procedure)
18
+ cf.connect
19
+ backups.each do |backup|
20
+ puts "\nDestroying backup \"#{backup.filename}\" from container \"#{backup.container}\"."
21
+ cf.destroy(backup.filename, backup.container)
22
+ backup.destroy
23
+ end
24
+ end
25
+
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,39 @@
1
+ require 'net/ftp'
2
+
3
+ module Backup
4
+ module Record
5
+ class FTP < Backup::Record::Base
6
+
7
+ attr_accessor :ip, :user, :password
8
+
9
+ def load_specific_settings(adapter)
10
+ %w(ip user password path).each do |method|
11
+ send(:"#{method}=", adapter.procedure.get_storage_configuration.attributes[method])
12
+ end
13
+ end
14
+
15
+ private
16
+
17
+ def self.destroy_backups(procedure, backups)
18
+ ip = procedure.get_storage_configuration.attributes['ip']
19
+ user = procedure.get_storage_configuration.attributes['user']
20
+ password = procedure.get_storage_configuration.attributes['password']
21
+
22
+ Net::FTP.open(ip, user, password) do |ftp|
23
+ backups.each do |backup|
24
+ puts "\nDestroying backup \"#{backup.filename}\" from path \"#{backup.path}\"."
25
+ begin
26
+ ftp.chdir(backup.path)
27
+ ftp.delete(backup.filename)
28
+ backup.destroy
29
+ rescue
30
+ puts "Could not find backup #{backup.path}/#{backup.filename}."
31
+ backup.destroy
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,26 @@
1
+ module Backup
2
+ module Record
3
+ class Local < Backup::Record::Base
4
+
5
+ def load_specific_settings(adapter)
6
+ self.path = adapter.procedure.get_storage_configuration.attributes['path']
7
+ end
8
+
9
+ private
10
+
11
+ class << self
12
+ include Backup::CommandHelper
13
+
14
+ def destroy_backups(procedure, backups)
15
+ backups.each do |backup|
16
+ puts "\nDestroying backup \"#{backup.filename}\" from path \"#{backup.path}\"."
17
+ run "rm #{File.join(backup.path, backup.filename)}"
18
+ backup.destroy
19
+ end
20
+ end
21
+ end
22
+
23
+ end
24
+ end
25
+ end
26
+
@@ -0,0 +1,26 @@
1
+ require 'backup/connection/s3'
2
+
3
+ module Backup
4
+ module Record
5
+ class S3 < Backup::Record::Base
6
+
7
+ def load_specific_settings(adapter)
8
+ self.bucket = adapter.procedure.get_storage_configuration.attributes['bucket']
9
+ end
10
+
11
+ private
12
+
13
+ def self.destroy_backups(procedure, backups)
14
+ s3 = Backup::Connection::S3.new
15
+ s3.static_initialize(procedure)
16
+ s3.connect
17
+ backups.each do |backup|
18
+ puts "\nDestroying backup \"#{backup.filename}\" from bucket \"#{backup.bucket}\"."
19
+ s3.destroy(backup.filename, backup.bucket)
20
+ backup.destroy
21
+ end
22
+ end
23
+
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,33 @@
1
+ require 'net/scp'
2
+
3
+ module Backup
4
+ module Record
5
+ class SCP < Backup::Record::Base
6
+
7
+ attr_accessor :ip, :user, :password
8
+
9
+ def load_specific_settings(adapter)
10
+ %w(ip user password path).each do |method|
11
+ send(:"#{method}=", adapter.procedure.get_storage_configuration.attributes[method])
12
+ end
13
+ end
14
+
15
+ private
16
+
17
+ def self.destroy_backups(procedure, backups)
18
+ ip = procedure.get_storage_configuration.attributes['ip']
19
+ user = procedure.get_storage_configuration.attributes['user']
20
+ password = procedure.get_storage_configuration.attributes['password']
21
+
22
+ Net::SSH.start(ip, user, :password => password) do |ssh|
23
+ backups.each do |backup|
24
+ puts "\nDestroying backup \"#{backup.filename}\" from path \"#{backup.path}\"."
25
+ ssh.exec("rm #{File.join(backup.path, backup.filename)}")
26
+ backup.destroy
27
+ end
28
+ end
29
+ end
30
+
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,38 @@
1
+ require 'net/sftp'
2
+
3
+ module Backup
4
+ module Record
5
+ class SFTP < Backup::Record::Base
6
+
7
+ attr_accessor :ip, :user, :password
8
+
9
+ def load_specific_settings(adapter)
10
+ %w(ip user password path).each do |method|
11
+ send(:"#{method}=", adapter.procedure.get_storage_configuration.attributes[method])
12
+ end
13
+ end
14
+
15
+ private
16
+
17
+ def self.destroy_backups(procedure, backups)
18
+ ip = procedure.get_storage_configuration.attributes['ip']
19
+ user = procedure.get_storage_configuration.attributes['user']
20
+ password = procedure.get_storage_configuration.attributes['password']
21
+
22
+ Net::SFTP.start(ip, user, :password => password) do |sftp|
23
+ backups.each do |backup|
24
+ puts "\nDestroying backup \"#{backup.filename}\" from path \"#{backup.path}\"."
25
+ begin
26
+ sftp.remove!(File.join(backup.path, backup.filename))
27
+ backup.destroy
28
+ rescue
29
+ puts "Could not find backup #{backup.path}/#{backup.filename}.."
30
+ backup.destroy
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,10 @@
1
+ module Backup
2
+ module Storage
3
+ class Base
4
+ include Backup::CommandHelper
5
+
6
+ end
7
+ end
8
+ end
9
+
10
+
@@ -0,0 +1,16 @@
1
+ require 'backup/connection/cloudfiles'
2
+
3
+ module Backup
4
+ module Storage
5
+ class CloudFiles < Base
6
+
7
+ # Stores the backup file on the remote server using Rackspace Cloud Files
8
+ def initialize(adapter)
9
+ cf = Backup::Connection::CloudFiles.new(adapter)
10
+ cf.connect
11
+ cf.store
12
+ end
13
+
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,38 @@
1
+ require 'net/ftp'
2
+
3
+ module Backup
4
+ module Storage
5
+ class FTP < Backup::Storage::Base
6
+
7
+ attr_accessor :user, :password, :ip, :path, :tmp_path, :final_file
8
+
9
+ # Stores the backup file on the remote server using FTP
10
+ def initialize(adapter)
11
+ %w(ip user password path).each do |method|
12
+ send("#{method}=", adapter.procedure.get_storage_configuration.attributes[method])
13
+ end
14
+
15
+ final_file = adapter.final_file
16
+ tmp_path = adapter.tmp_path
17
+
18
+ Net::FTP.open(ip, user, password) do |ftp|
19
+ begin
20
+ ftp.chdir(path)
21
+ rescue
22
+ puts "Could not find or access \"#{path}\" on \"#{ip}\", please ensure this directory exists and is accessible by the user \"#{user}\"."
23
+ exit
24
+ end
25
+
26
+ begin
27
+ puts "Storing \"#{final_file}\" to path \"#{path}\" on remote server (#{ip})."
28
+ ftp.putbinaryfile(File.join(tmp_path, final_file).gsub('\ ', ' '), File.join(path, final_file))
29
+ rescue
30
+ puts "Could not save file to backup server. Is the \"#{path}\" directory writable?"
31
+ exit
32
+ end
33
+ end
34
+ end
35
+
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,22 @@
1
+ module Backup
2
+ module Storage
3
+ class Local < Base
4
+
5
+ # Store on same machine, preferentially in a different hard drive or in
6
+ # a mounted network path (NFS, Samba, etc)
7
+ attr_accessor :path, :tmp_path, :final_file
8
+
9
+ # Stores the backup file on local machine
10
+ def initialize(adapter)
11
+ self.path = adapter.procedure.get_storage_configuration.attributes['path']
12
+ self.tmp_path = adapter.tmp_path
13
+ self.final_file = adapter.final_file
14
+
15
+ run "mkdir -p #{path}"
16
+ run "cp #{File.join(tmp_path, final_file).gsub('\ ', ' ')} #{File.join(path, final_file)}"
17
+ end
18
+
19
+ end
20
+ end
21
+ end
22
+
@@ -0,0 +1,17 @@
1
+ require 'backup/connection/s3'
2
+
3
+ module Backup
4
+ module Storage
5
+ class S3 < Base
6
+
7
+ # Stores the backup file on the remote server using S3
8
+ def initialize(adapter)
9
+ s3 = Backup::Connection::S3.new(adapter)
10
+ s3.connect
11
+ log("Saving '#{s3.final_file}' to s3 bucket '#{s3.s3_bucket}'")
12
+ s3.store
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,30 @@
1
+ require 'net/scp'
2
+
3
+ module Backup
4
+ module Storage
5
+ class SCP < Base
6
+
7
+ attr_accessor :user, :password, :ip, :path, :tmp_path, :final_file
8
+
9
+ # Stores the backup file on the remote server using SCP
10
+ def initialize(adapter)
11
+ %w(ip user password path).each do |method|
12
+ send("#{method}=", adapter.procedure.get_storage_configuration.attributes[method])
13
+ end
14
+
15
+ final_file = adapter.final_file
16
+ tmp_path = adapter.tmp_path
17
+
18
+ Net::SSH.start(ip, user, :password => password) do |ssh|
19
+ ssh.exec "mkdir -p #{path}"
20
+ end
21
+
22
+ puts "Storing \"#{final_file}\" to path \"#{path}\" on remote server (#{ip})."
23
+ Net::SCP.start(ip, user, :password => password) do |scp|
24
+ scp.upload! File.join(tmp_path, final_file).gsub('\ ', ' '), path
25
+ end
26
+ end
27
+
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,31 @@
1
+ require 'net/sftp'
2
+
3
+ module Backup
4
+ module Storage
5
+ class SFTP < Base
6
+
7
+ attr_accessor :user, :password, :ip, :path, :tmp_path, :final_file
8
+
9
+ # Stores the backup file on the remote server using SFTP
10
+ def initialize(adapter)
11
+ %w(ip user password path).each do |method|
12
+ send("#{method}=", adapter.procedure.get_storage_configuration.attributes[method])
13
+ end
14
+
15
+ final_file = adapter.final_file
16
+ tmp_path = adapter.tmp_path
17
+
18
+ Net::SFTP.start(ip, user, :password => password) do |sftp|
19
+ begin
20
+ puts "Storing \"#{final_file}\" to path \"#{path}\" on remote server (#{ip})."
21
+ sftp.upload!(File.join(tmp_path, final_file).gsub('\ ', ' '), File.join(path, final_file))
22
+ rescue
23
+ puts "Could not find \"#{path}\" on \"#{ip}\", please ensure this directory exists."
24
+ exit
25
+ end
26
+ end
27
+ end
28
+
29
+ end
30
+ end
31
+ end