class SyncPointRestore

Public Class Methods

ask_missing_db_action() click to toggle source
# File lib/sync_point_restore.rb, line 7
def self.ask_missing_db_action
  answer = ''
  options = '[I/e/d]'
  d = 'i'
  until %w[i e d].include? answer
    answer = ask("[I]gnore the error, [e]dit the file, or [d]elete it? #{options} ") { |q| q.limit = 1; q.case = :downcase }
    answer = d if answer.length == 0
  end
  case answer
    when 'i'
      return :ignore
    when 'e'
      return :edit
    when 'd'
      return :delete
  end
end
restore_configs(sync_point_dir, dest_dir) click to toggle source
# File lib/sync_point_restore.rb, line 108
def self.restore_configs(sync_point_dir, dest_dir)
  failValidation if (!sync_point_dir.is_a?(String)) or (!dest_dir.is_a?(String))
  FileUtils.rm_rf("#{dest_dir}.bak") if File.exists?("#{dest_dir}.bak")
  FileUtils.move(dest_dir, "#{dest_dir}.bak")
  Dir.mkdir(dest_dir)

  if File.exists?(File.join("#{dest_dir}.bak", 'config.ini'))
    FileUtils.copy(File.join("#{dest_dir}.bak", 'config.ini'), File.join(dest_dir, 'config.ini'))
  end

  FileUtils.cp_r(Dir[File.join(sync_point_dir, 'configs', '*')], dest_dir)


  abbrvs = {'ian' => 1, 'feb' => 2, 'mar' => 3, 'apr' => 4, 'mai' => 5, 'iunie' => 6, 'iulie' => 7, 'aug' => 8, 'sept' => 9, 'oct' => 10, 'noem' => 11, 'dec' => 12}
  reverse_abbrvs = abbrvs.invert

  dbs = {}
  temp = `mysql -u #{$db_user} --password='#{$db_pass}' -B -N -e 'show databases' -h #{$db_host} -P#{$db_port}`.split("\n")

  temp.each do |db|
    next unless db =~ /(.*?)(3[01]|[012]\d)(ian|feb|mar|apr|mai|iunie|iulie|aug|sept|oct|noem|dec)/
    results = db.scan(/(.*?)(3[01]|[012]\d)(ian|feb|mar|apr|mai|iunie|iulie|aug|sept|oct|noem|dec)/).flatten

    name  = results[0]
    day   = results[1]
    month = results[2].downcase

    dbs[name] = {} if not dbs.has_key?(name)
    dbs[name][abbrvs[month]] = [] if not dbs[name].has_key?(abbrvs[month])
    dbs[name][abbrvs[month]].push(Integer(day))
  end

  Find.find(dest_dir) do |file|
    next unless File.file?(file)

    filename  = file.scan(/#{dest_dir}\/?(.*)/).flatten[0]
    next if filename == 'config.ini'

    text = File.read(file).gsub("\"", "'")

    text.gsub!(/params.hostname(\s*)=(\s*)''/m, "params.hostname\\1=\\2'85.204.164.82'")
    text.gsub!(/params.username(\s*)=(\s*)''/m, "params.username\\1=\\2'root'")
    text.gsub!(/params.password(\s*)=(\s*)''/m, "params.password\\1=\\2'd31abedfa226ebaf8c7a06dcbd1cdfa953cc32004c7d5dc9e2c2699c8b959096DjtiK6AV6QD9reCjaNqDA0wzFYkBeDFvcKWdd0rDimY='")
    text.gsub!(/BucketName(\s*)=(\s*)''/m, "BucketName\\1=\\2'my1outsourcing2-bucket'")

    db_name, db_suffix = text.scan(/params.database\s*=\s*'([^']*?)(db)?'/).flatten

    if dbs.has_key?(db_name)
      latest_month = reverse_abbrvs[dbs[db_name].keys.max]
      latest_day = dbs[db_name][dbs[db_name].keys.max].max
      text.gsub!(/params.database(\s*)=(\s*)'[^']*'/m, "params.database\\1=\\2'#{db_name}#{latest_day}#{latest_month}'")
    else
      puts "Error Synchronizing subdomain config file: #{file}"
      puts "Subdomain config file uses the database '#{db_name}#{db_suffix}' but no equivalent database exists on MySQL host."

      case ask_missing_db_action()
        when :edit
          tmpfile = Tempfile.new('insxsync')
          begin
            tmpfile.write(text)
            editor = which("nano", "vi", "emacs")
            if editor.not_nil?
              system("#{editor} #{tmpfile.path}")
              tmpfile.rewind
              temp_text = tmpfile.read
              if temp_text == text
                $stderr.puts "File not edited. Ignoring error and continuing synchronization..."
                next
              end
              tmpfile.rewind
              text = temp_text
            else
              $stderr.puts "Unable to find a valid editor (checked for vi, nano, emacs). Ignoring error and continuing synchronization..."
              next
            end
          ensure
            tmpfile.close
            tmpfile.unlink
          end
        when :delete
          File.delete(file)
          next
      end
    end
    File.write(file, text)
  end

  Find.find(dest_dir) do |file|
    puts "Test: #{file}"
  end

  Find.find(dest_dir) do |file|
    next if file == "."
    next if file == ".."
    next if file == dest_dir
    next unless File.directory?(file)

    dirname  = file.scan(/#{dest_dir}\/?(.*)/).flatten[0]
    puts "Dirname: #{dirname}"
    unless dirname =~ /dev.*/
      FileUtils.move(File.join(dest_dir, dirname), File.join(dest_dir, "dev#{dirname}"))
    end
  end
end
restore_data(sync_point_dir, time, databases) click to toggle source
# File lib/sync_point_restore.rb, line 213
def self.restore_data(sync_point_dir, time, databases)
  abbrvs = {'ian' => 1, 'feb' => 2, 'mar' => 3, 'apr' => 4, 'mai' => 5, 'iunie' => 6, 'iulie' => 7, 'aug' => 8, 'sept' => 9, 'oct' => 10, 'noem' => 11, 'dec' => 12}
  reverse_abbrvs = abbrvs.invert

  day = Time.at(time.to_i).strftime('%d')
  month = reverse_abbrvs[Time.at(time.to_i).strftime('%m').to_i]

  backup_dbs = []
  Find.find(File.join(sync_point_dir, 'database')) do |file|
    next if File.directory?(file)
    old_name = File.basename(file, '.sql')
    backup_dbs.push(old_name)
    new_name = old_name.scan(/\A(.*?)(db)?\z/).flatten[0] + day + month
    tmpfile = File.open("#{file}.tmp", 'w')
    tmppath = tmpfile.path
    File.open(file, 'r').each_line do |line|
      line.gsub!(/ndbcluster/i, "innodb")
      line.gsub!(/#{old_name}/i, new_name)
      tmpfile.write(line)
    end
    tmpfile.close
    FileUtils.mv(tmpfile.path, file)
  end

  if databases.not_nil?
      databases.each do |item|
        require_condition backup_dbs.count(item) == 1, "\nArgument Error: Database \"#{item}\" does not exist in specified backup. No changes made. Exiting..."
      end
  end


  Find.find(File.join(sync_point_dir, 'database')) do |file|
    next if File.directory?(file)

    if databases.not_nil?
      next unless databases.count(File.basename(file, '.sql')) == 1
    end

    mysql = which("mysql")
    raise if mysql.nil?


    `#{mysql} -u #{$db_user} --password='#{$db_pass}' -h #{$db_host} -P#{$db_port} < #{file}`
    if $?.exitstatus != 0
      puts "Error: Unknown error importing #{file}."
      if yesno("Would you like to revert the import of this file?", false)
          dump = File.open(file, 'r')
          db_name = nil
          until db_name.not_nil?
            line = dump.readline
            if line =~ /use\s*`([^']*?)`/i
              db_name = line.scan(/use\s*`([^']*)`/i).flatten[0]
            end
          end
          `mysql -u #{$db_user} --password='#{$db_pass}' -e 'drop schema \`#{db_name}\`' -h #{$db_host} -P#{$db_port}`
          if $?.exitstatus == 0
            puts "Import reverted successfully. Continuing..."
          else
            puts "Unknown error reverting import. Continuing..."
          end
      end
    end

    dump = File.open(file, 'r')
    db_name = nil
    until db_name.not_nil?
      line = dump.readline
      if line =~ /use\s*`([^']*?)`/i
        db_name = line.scan(/use\s*`([^']*)`/i).flatten[0]
      end
    end

    begin
      dbh = Mysql.real_connect($db_host, $db_user, $db_pass, db_name, $db_port)
      password_update = dbh.real_query("UPDATE  `User` SET  `Password`='92a891f888e79d1c2e8b82663c0f37cc6d61466c508ec62b8132588afe354712b20bb75429aa20aa3ab7cfcc58836c734306b43efd368080a2250831bf7f363f'")
      email_update = dbh.real_query("UPDATE `ContactDetail` set `Email`='test@my1outsourcing.com'")
    rescue Mysql::Error => e
      if e.error =~ /Can't connect to MySQL server/
        $stderr.puts "MySQL host at #{$db_host}:#{$db_port} did not respond. No actions performed. Exiting..."
        exit -1
      elsif e.error =~ /Access denied for user/
        $stderr.puts "MySQL access denied for user '#{$db_user}' (using password: #{$db_pass.nil? ? "NO" : "YES"}). No actions performed. Exiting..."
        exit -1
      end

      puts e
      $stderr.puts "Some other mysql error during import."
      exit -1
    ensure
      dbh.close if dbh
    end



    #`mysql -u #{$db_user} --password='#{$db_pass}' -b '#{db_name}' -e  -h #{$db_host} -P#{$db_port}`
    #`mysql -u #{$db_user} --password='#{$db_pass}' -b '#{db_name}' -e "UPDATE \`ContactDetail\` set \`Email\`='test@my1outsourcing.com'" -h #{$db_host} -P#{$db_port}`
  end
end
restore_data_uat(dir) click to toggle source
# File lib/sync_point_restore.rb, line 312
def self.restore_data_uat(dir)
  Find.find(File.join(dir, 'database')) do |file|
    next if File.directory?(file)
    old_name = File.basename(file, '.sql')
    new_name = 'dev' + old_name
    tmpfile = File.open("#{file}.tmp", 'w')
    File.open(file, 'r').each_line do |line|
      line.gsub!(/#{old_name}/i, new_name)
      tmpfile.write(line)
    end
    tmpfile.close
    FileUtils.mv(tmpfile.path, file)
  end

  dbs = `#{which('mysql')} -u #{$db_user} --password='#{$db_pass}' -B -N -e 'show databases' -h #{$db_host} -P#{$db_port}`.split("\n")
  dbs.select! do |db|
    case db
      when 'mysql'
        false
      when 'information_schema'
        false
      when 'performance_schema'
        false
      when 'ndbinfo'
        false
      when 'test'
        false
      else
        true
    end
  end

  recovery_dumps = []
  failed = false

  Find.find(File.join(dir, 'database')) do |file|
    next if File.directory?(file)
    mysql = which("mysql")
    raise if mysql.nil?

    old_name = File.basename(file, '.sql')
    new_name = 'dev' + old_name
    has_backup = false
    temp_dump = nil

    if dbs.include?(new_name)
      temp_dump = Dir::Tmpname.create([new_name, '.sql'], nil) {}
      print "Taking recovery dump for '#{new_name}'...\t\t"
      `#{which('mysqldump')} -u #{$db_user} --password='#{$db_pass}' -h #{$db_host} -P#{$db_port} --add-drop-database --databases #{new_name} > #{temp_dump}`
      if $?.exitstatus == 0
        puts "Done."
        has_backup = true
        recovery_dumps.push([temp_dump, new_name])
      else
        puts "ERROR!\nUnknown error occured during dump. No recover dump for '#{new_name}'. Continuing..."
        File.delete(temp_dump) if File.exists?(temp_dump)
        temp_dump = nil
      end

      if has_backup
        print "Dropping existing schema for '#{new_name}'...\t\t"
        `mysql -u #{$db_user} --password='#{$db_pass}' -e 'DROP SCHEMA \`#{new_name}\`' -h #{$db_host} -P#{$db_port}`
        puts "Done."
      else
        if yesno("WARNING: No recovery dump created for '#{new_name}'. In the event of an error, '#{new_name}' cannot be reverted and will be dropped. Do you wish to abort the synchronization?", false)
          failed = true
          break
        end
        next if yesno("Synchronization continuing. Do you wish to skip the synchronization of '#{new_name}'?", true)

        print "Dropping existing schema for '#{new_name}'...\t\t"
        `mysql -u #{$db_user} --password='#{$db_pass}' -e 'DROP SCHEMA \`#{new_name}\`' -h #{$db_host} -P#{$db_port}`
        puts "Done."        end
    end

    print "Importing schema for '#{new_name}'...\t\t"
    `#{mysql} -u #{$db_user} --password='#{$db_pass}' -h #{$db_host} -P#{$db_port} < #{file}`
    puts "Done."

    if $?.exitstatus != 0
      if has_backup
        puts "Error: Unknown error importing #{new_name}."
        if yesno("Would you like to revert the import of this databse?", false)
          new_dbs = `#{which('mysql')} -u #{$db_user} --password='#{$db_pass}' -B -N -e 'show databases' -h #{$db_host} -P#{$db_port}`.split("\n")
          if new_dbs.include?(new_name)
            print "Dropping schema for incomplete import of '#{new_name}'...\t\t"
            `mysql -u #{$db_user} --password='#{$db_pass}' -e 'DROP SCHEMA \`#{new_name}\`' -h #{$db_host} -P#{$db_port}`
            puts "Done."
          end
          print "Imporitng recovery dump for '#{new_name}'...\t\t"
          `#{mysql} -u #{$db_user} --password='#{$db_pass}' -h #{$db_host} -P#{$db_port} < #{temp_dump}`
          `mysql -u #{$db_user} --password='#{$db_pass}' -e "UPDATE  \`#{new_name}\`.\`User\` SET  \`Password\` =  '92a891f888e79d1c2e8b82663c0f37cc6d61466c508ec62b8132588afe354712b20bb75429aa20aa3ab7cfcc58836c734306b43efd368080a2250831bf7f363f'" -h #{$db_host} -P#{$db_port}`
          `mysql -u #{$db_user} --password='#{$db_pass}' -e "UPDATE \`#{new_name}\`.\`ContactDetail\` set \`Email\` = 'test@my1outsourcing.com'" -h #{$db_host} -P#{$db_port}`
          puts "Done."
        end
        unless yesno("Would you like to abort the synchronization?", false)
          failed = true
          break
        end
      else
        puts "Error: Unknown error importing #{new_name}."
        new_dbs = `#{which('mysql')} -u #{$db_user} --password='#{$db_pass}' -B -N -e 'show databases' -h #{$db_host} -P#{$db_port}`.split("\n")
        if new_dbs.include?(new_name)
          print "Dropping schema for incomplete import of '#{new_name}'...\t\t"
          `mysql -u #{$db_user} --password='#{$db_pass}' -e 'DROP SCHEMA \`#{new_name}\`' -h #{$db_host} -P#{$db_port}`
          puts "Done."
        end
        unless yesno("Would you like to abort the synchronization?", false)
          failed = true
          break
        end
      end
    end
  end

  if failed and yesno("Synchronization aborted! Would you like to revert all changes (all recovery dumps will be restored)?")
    new_dbs = `#{which('mysql')} -u #{$db_user} --password='#{$db_pass}' -B -N -e 'show databases' -h #{$db_host} -P#{$db_port}`.split("\n")
    recovery_dumps.each do |dump|
      if new_dbs.include?(dump[1])
        print "Dropping schema for import imported database '#{dump[1]}'...\t\t"
        `mysql -u #{$db_user} --password='#{$db_pass}' -e 'DROP SCHEMA \`#{dump[1]}\`' -h #{$db_host} -P#{$db_port}`
        puts "Done."
      end
      print "Imporitng recovery dump for '#{dump[1]}'...\t\t"
      `#{mysql} -u #{$db_user} --password='#{$db_pass}' -h #{$db_host} -P#{$db_port} < #{dump[0]}`
      puts "Done."

    end
  end

  print "Deleting recovery dumps...\t\t"
  recovery_dumps.each do |dump|
    File.delete(dump[0])
  end
  done "Done."
end
update_configs(config_dir) click to toggle source
# File lib/sync_point_restore.rb, line 25
def self.update_configs(config_dir)
  FileUtils.rm_rf("#{config_dir}.bak") if File.exists?("#{config_dir}.bak")
  FileUtils.move(config_dir, "#{config_dir}.bak")
  Dir.mkdir(config_dir)

  FileUtils.cp_r(Dir[File.join("#{config_dir}.bak", '*')], config_dir)

  abbrvs = {'ian' => 1, 'feb' => 2, 'mar' => 3, 'apr' => 4, 'mai' => 5, 'iunie' => 6, 'iulie' => 7, 'aug' => 8, 'sept' => 9, 'oct' => 10, 'noem' => 11, 'dec' => 12}
  reverse_abbrvs = abbrvs.invert

  dbs = {}
  temp = `mysql -u #{$db_user} --password='#{$db_pass}' -B -N -e 'show databases' -h #{$db_host} -P#{$db_port}`.split("\n")

  temp.each do |db|
    next unless db =~ /(.*?)(3[01]|[012]\d)(ian|feb|mar|apr|mai|iunie|iulie|aug|sept|oct|noem|dec)/
    results = db.scan(/(.*?)(3[01]|[012]\d)(ian|feb|mar|apr|mai|iunie|iulie|aug|sept|oct|noem|dec)/).flatten

    name  = results[0]
    day   = results[1]
    month = results[2].downcase

    dbs[name] = {} if not dbs.has_key?(name)
    dbs[name][abbrvs[month]] = [] if not dbs[name].has_key?(abbrvs[month])
    dbs[name][abbrvs[month]].push(Integer(day))
  end


  Find.find(config_dir) do |file|
    next if File.directory?(file)

    filename  = file.scan(/#{config_dir}\/?(.*)/).flatten[0]
    next if filename == 'config.ini'

    text = File.read(file).gsub("\"", "'")

    text.gsub!(/params.hostname(\s*)=(\s*)'[^']*'/m, "params.hostname\\1=\\2'85.204.164.82'")
    text.gsub!(/params.username(\s*)=(\s*)'[^']*'/m, "params.username\\1=\\2'root'")
    text.gsub!(/params.password(\s*)=(\s*)'[^']*'/m, "params.password\\1=\\2'd31abedfa226ebaf8c7a06dcbd1cdfa953cc32004c7d5dc9e2c2699c8b959096DjtiK6AV6QD9reCjaNqDA0wzFYkBeDFvcKWdd0rDimY='")
    text.gsub!(/BucketName(\s*)=(\s*)'[^']*'/m, "BucketName\\1=\\2'my1outsourcing2-bucket'")

    db_name, db_suffix = text.scan(/params.database\s*=\s*'([^']*?)(db|3[01][^']*|[0-2]\d[^']*)?'/).flatten

    if dbs.has_key?(db_name)
      latest_month = reverse_abbrvs[dbs[db_name].keys.max]
      latest_day = dbs[db_name][dbs[db_name].keys.max].max
      text.gsub!(/params.database(\s*)=(\s*)'[^']*'/m, "params.database\\1=\\2'#{db_name}#{latest_day}#{latest_month}'")
    else
      puts "Error updating subdomain config file: #{file}"
      puts "Subdomain config file uses the database '#{db_name}#{db_suffix}' but no equivalent database exists on MySQL host."

      case ask_missing_db_action()
        when :edit
          tmpfile = Tempfile.new('insxsync')
          begin
            tmpfile.write(text)
            editor = which("nano", "vi", "emacs")
            if editor.not_nil?
              system("#{editor} #{tmpfile.path}")
              tmpfile.rewind
              temp_text = tmpfile.read
              if temp_text == text
                $stderr.puts "File not edited. Ignoring error and continuing update..."
                next
              end
              tmpfile.rewind
              text = temp_text
            else
              $stderr.puts "Unable to find a valid editor (checked for vi, nano, emacs). Ignoring error and continuing update..."
              next
            end
          ensure
            tmpfile.close
            tmpfile.unlink
          end
        when :delete
          File.delete(file)
          next
      end
    end
    File.write(file, text)
  end
end