Skip to content

Commit

Permalink
Add EvmDatabaseOps#dump
Browse files Browse the repository at this point in the history
Runs using the same setup as EvmDatabaseOps#backup, but runs a `pg_dump`
under the hood.  It uses the same method for determining if there is
enough diskspace for the dump as the backup method.  This isn't 100%
accurate, but it should be "Good Enough™".
  • Loading branch information
NickLaMuro committed May 25, 2018
1 parent 3d5b2b0 commit c4e7793
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 7 deletions.
27 changes: 20 additions & 7 deletions lib/evm_database_ops.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@

class EvmDatabaseOps
include Vmdb::Logging
BACKUP_TMP_FILE = "/tmp/miq_backup"
BACKUP_TMP_FILE = "/tmp/miq_backup".freeze
DUMP_TMP_FILE = "/tmp/miq_pg_dump".freeze

DEFAULT_OPTS = {:dbname => 'vmdb_production'}

Expand All @@ -28,13 +29,21 @@ def self.database_size(opts)
end

def self.backup(db_opts, connect_opts = {})
uri = run_db_opt_for_new_uri(db_opts, connect_opts) do |database_opts|
uri = run_db_opt_for_new_uri(:backup, db_opts, connect_opts) do |database_opts|
PostgresAdmin.backup(database_opts)
end
_log.info("[#{db_opts[:dbname]}] database has been backed up to file: [#{uri}]")
uri
end

def self.dump(db_opts, connect_opts = {})
uri = run_db_opt_for_new_uri(:dump, db_opts, connect_opts) do |database_opts|
PostgresAdmin.backup_pg_dump(database_opts)
end
_log.info("[#{db_opts[:dbname]}] database has been dumped up to file: [#{uri}]")
uri
end

# db_opts:
# :dbname => 'vmdb_production',
# :username => 'root',
Expand All @@ -45,18 +54,22 @@ def self.backup(db_opts, connect_opts = {})
# :username => 'samba_one',
# :password => 'Zug-drep5s',
# :remote_file_name => "backup_1", - Provide a base file name for the uploaded file
private_class_method def self.run_db_opt_for_new_uri(db_opts, connect_opts = {})
private_class_method def self.run_db_opt_for_new_uri(action, db_opts, connect_opts = {})
db_opts = DEFAULT_OPTS.merge(db_opts)

if db_opts[:local_file].nil?
connect_opts[:remote_file_name] ||= File.basename(backup_file_name)
connect_opts[:remote_file_name] ||= File.basename(backup_file_name(action))

session = MiqGenericMountSession.new_session(connect_opts)

uri = File.join(connect_opts[:uri], "db_backup", connect_opts[:remote_file_name])
backup_folder = action == :dump ? "db_dump" : "db_backup"
uri = File.join(connect_opts[:uri], backup_folder, connect_opts[:remote_file_name])
db_opts[:local_file] = session.uri_to_local_path(uri)
end

# For database dumps, this isn't going to be as accurate, but it still
# won't hurt to do as a generic way to get a rough idea if we have enough
# disk space or the appliance for the task.
free_space = backup_destination_free_space(db_opts[:local_file])
db_size = database_size(db_opts)
if free_space > db_size
Expand Down Expand Up @@ -168,9 +181,9 @@ def self.download(connect_opts, local_file)
local_file
end

def self.backup_file_name
def self.backup_file_name(action = :backup)
time_suffix = Time.now.utc.strftime("%Y%m%d_%H%M%S")
"#{BACKUP_TMP_FILE}_#{time_suffix}"
"#{action == :backup ? BACKUP_TMP_FILE : DUMP_TMP_FILE}_#{time_suffix}"
end
private_class_method :backup_file_name
end
46 changes: 46 additions & 0 deletions spec/lib/evm_database_ops_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,52 @@
end
end

context "#dump" do
before do
@connect_opts = {:username => 'blah', :password => 'blahblah', :uri => "smb://myserver.com/share"}
@db_opts = {:dbname => 'vmdb_production', :username => 'root'}
allow(MiqSmbSession).to receive(:runcmd)
allow_any_instance_of(MiqSmbSession).to receive(:settings_mount_point).and_return(Rails.root.join("tmp"))
allow(MiqUtil).to receive(:runcmd)
allow(PostgresAdmin).to receive(:runcmd_with_logging)
allow(FileUtils).to receive(:mv).and_return(true)
allow(EvmDatabaseOps).to receive(:backup_destination_free_space).and_return(200.megabytes)
allow(EvmDatabaseOps).to receive(:database_size).and_return(100.megabytes)
end

it "locally" do
local_dump = "/tmp/dump_1"
@db_opts[:local_file] = local_dump
expect(EvmDatabaseOps.dump(@db_opts, @connect_opts)).to eq(local_dump)
end

it "defaults" do
local_dump = "/tmp/dump_1"
@db_opts[:local_file] = local_dump
expect(EvmDatabaseOps.dump(@db_opts, {})).to eq(local_dump)
end

it "without enough free space" do
EvmSpecHelper.create_guid_miq_server_zone
allow(EvmDatabaseOps).to receive(:backup_destination_free_space).and_return(100.megabytes)
allow(EvmDatabaseOps).to receive(:database_size).and_return(200.megabytes)
expect { EvmDatabaseOps.dump(@db_opts, @connect_opts) }.to raise_error(MiqException::MiqDatabaseBackupInsufficientSpace)
expect(MiqQueue.where(:class_name => "MiqEvent", :method_name => "raise_evm_event").count).to eq(1)
end

it "remotely" do
@db_opts[:local_file] = nil
@connect_opts[:remote_file_name] = "custom_pg_dump"
expect(EvmDatabaseOps.dump(@db_opts, @connect_opts)).to eq("smb://myserver.com/share/db_dump/custom_pg_dump")
end

it "remotely without a remote file name" do
@db_opts[:local_file] = nil
@connect_opts[:remote_file_name] = nil
expect(EvmDatabaseOps.dump(@db_opts, @connect_opts)).to match(/smb:\/\/myserver.com\/share\/db_dump\/miq_pg_dump_.*/)
end
end

context "#restore" do
before do
@connect_opts = {:username => 'blah', :password => 'blahblah'}
Expand Down

0 comments on commit c4e7793

Please sign in to comment.