diff --git a/src/onedb/onedb b/src/onedb/onedb index 6d4d8916a1..c555ff2bb3 100755 --- a/src/onedb/onedb +++ b/src/onedb/onedb @@ -189,6 +189,13 @@ SLAVE_DBNAME={ } } +SLAVE_BACKUP={ + :name => "slave-backup", + :large => "--slave-backup file", + :description => "Use this file to store SQL dump", + :format => String +} + cmd=CommandParser::CmdParser.new(ARGV) do description <<-EOT.unindent This command enables the user to manage the OpenNebula database. It @@ -311,7 +318,8 @@ cmd=CommandParser::CmdParser.new(ARGV) do EOT command :"import-slave", import_slave_desc, :options=>[FORCE,BACKUP, - SLAVE_SERVER,SLAVE_PORT,SLAVE_USERNAME,SLAVE_PASSWORD,SLAVE_DBNAME] do + SLAVE_SERVER,SLAVE_PORT,SLAVE_USERNAME,SLAVE_PASSWORD, + SLAVE_DBNAME,SLAVE_BACKUP] do begin helper = OneDB.new(options) diff --git a/src/onedb/onedb.rb b/src/onedb/onedb.rb index 230899a554..2892d36ff3 100644 --- a/src/onedb/onedb.rb +++ b/src/onedb/onedb.rb @@ -39,12 +39,7 @@ class OneDB passwd = ops[:passwd] if !passwd - # Hide input characters - `stty -echo` - print "MySQL Password: " - passwd = STDIN.gets.strip - `stty echo` - puts "" + passwd = get_password end @backend = BackEndMySQL.new( @@ -59,20 +54,31 @@ class OneDB end end - def backup(bck_file, ops) - bck_file = @backend.bck_file if bck_file.nil? + def get_password(question="MySQL Password: ") + # Hide input characters + `stty -echo` + print question + passwd = STDIN.gets.strip + `stty echo` + puts "" + + return passwd + end + + def backup(bck_file, ops, backend=@backend) + bck_file = backend.bck_file if bck_file.nil? if !ops[:force] && File.exists?(bck_file) raise "File #{bck_file} exists, backup aborted. Use -f " << "to overwrite." end - @backend.backup(bck_file) + backend.backup(bck_file) return 0 end - def restore(bck_file, ops) - bck_file = @backend.bck_file if bck_file.nil? + def restore(bck_file, ops, backend=@backend) + bck_file = backend.bck_file if bck_file.nil? if !File.exists?(bck_file) raise "File #{bck_file} doesn't exist, backup restoration aborted." @@ -80,7 +86,7 @@ class OneDB one_not_running - @backend.restore(bck_file, ops[:force]) + backend.restore(bck_file, ops[:force]) return 0 end @@ -233,26 +239,13 @@ class OneDB end def import_slave(ops) - - # TODO: Check backend is not sqlite - - # TODO: refactor, same code in initialize() - begin - require 'mysql' - rescue LoadError - STDERR.puts "Ruby gem mysql is needed for this operation:" - STDERR.puts " $ sudo gem install mysql" - exit -1 + if ops[:backend] == :sqlite + raise "Master DB must be MySQL" end passwd = ops[:slave_passwd] if !passwd - # Hide input characters - `stty -echo` - print "Slave MySQL Password: " - passwd = STDIN.gets.strip - `stty echo` - puts "" + passwd = get_password("Slave MySQL Password: ") end slave_backend = BackEndMySQL.new( @@ -298,14 +291,47 @@ class OneDB # Import will be executed, make DB backup backup(ops[:backup], ops) + backup(ops[:"slave-backup"], ops, slave_backend) - # TODO: slave backup + puts <<-EOT +The import process will move the users from the slave OpeNenbula to the master +OpenNebula. In case of conflict, it can merge users with the same name. +For example: ++----------+-------------++------------+---------------+ +| Master | Slave || With merge | Without merge | ++----------+-------------++------------+---------------+ +| 5, alice | 2, alice || 5, alice | 5, alice | +| 6, bob | 5, bob || 6, bob | 6, bob | +| | || | 7, alice-1 | +| | || | 8, bob-1 | ++----------+-------------++------------+---------------+ + +In any case, the ownership of existing resources and group membership +is preserved. + + EOT + + input = "" + while !( ["Y", "N"].include?(input) ) do + print "Do you want to merge USERS (Y/N): " + input = gets.chomp.upcase + end + + merge_users = input == "Y" + puts + + input = "" + while !( ["Y", "N"].include?(input) ) do + print "Do you want to merge GROUPS (Y/N): " + input = gets.chomp.upcase + end + + merge_groups = input == "Y" begin puts " > Running slave import" if ops[:verbose] - # TODO: ask about merge - result = @backend.import_slave(slave_backend, true, true) + result = @backend.import_slave(slave_backend, merge_users, merge_groups) if !result raise "Error running slave import version #{version}" @@ -319,11 +345,12 @@ class OneDB puts e.message puts "Error running slave import version #{version}" - puts "The database will be restored" + puts "The databases will be restored" ops[:force] = true restore(ops[:backup], ops) + restore(ops[:"slave-backup"], ops, slave_backend) return -1 end diff --git a/src/onedb/onedb_backend.rb b/src/onedb/onedb_backend.rb index ee8063e6ea..3832bc20ab 100644 --- a/src/onedb/onedb_backend.rb +++ b/src/onedb/onedb_backend.rb @@ -177,6 +177,7 @@ class BackEndMySQL < OneDBBacKEnd puts "MySQL dump stored in #{bck_file}" puts "Use 'onedb restore' or restore the DB using the mysql command:" puts "mysql -u user -h server -P port db_name < backup_file" + puts end def restore(bck_file, force=nil) @@ -238,6 +239,7 @@ class BackEndSQLite < OneDBBacKEnd FileUtils.cp(@sqlite_file, "#{bck_file}") puts "Sqlite database backup stored in #{bck_file}" puts "Use 'onedb restore' or copy the file back to restore the DB." + puts end def restore(bck_file, force=nil)