lib/roma/tools/cpdb.rb

Summary

Maintainability
A
25 mins
Test Coverage
#!/usr/bin/env ruby

require 'socket'

module Roma
  class SafeCopy

    attr_reader :storages

    def initialize(addr, port)
      @con = TCPSocket.open(addr, port)
      set_gui_run_snapshot_status('true')
      get_storage_info
    end

    def backup_all
      @storages.keys.each do |k|
        backup(k)
      end
    end

    def check_storage_type
      stats('st_class') do |line|
        storage_type = line.match(/storages\[.+\]\.storage\.st_class\s(.+)/)[1].chomp
        unless storage_type =~ /^(TCStorage)$/
          puts "ERROR:cpdb supports just TCStorage system, your storage type is #{storage_type}"
          exit
        end
      end
    end

    def backup(hname)
      stat = get_safecopy_stats(hname)
      if stat.uniq != [:normal]
        puts "storages[#{hname}].storage.safecopy_stats #{stat.to_s}"
        puts "ERROR: Status except the :normal exists."
        return
      end
      @storages[hname].each_with_index do |fname, num|
        ret = set_storage_status(hname, num, "safecopy")
        if ret != "PUSHED\r\n"
          puts ret
          puts "ERROR: Can't change storage status to safecopy."
          return
        end
        wait(hname, num, :safecopy_flushed)
        puts "copy file : #{fname}"
        # file copy
        `cp #{fname} #{fname}.#{Time.now.strftime("%Y%m%d%H%M%S")}`
        ret = set_storage_status(hname, num, "normal") 
        if ret != "PUSHED\r\n"
          puts ret
          puts "ERROR: Can't change storage status to normal."
          return
        end
        wait(hname, num, :normal)
      end
    end

    def wait(hname, num, stat)
      print "waiting for storages[#{hname}][#{num}] == #{stat} "
      while get_safecopy_stats(hname)[num] != stat
        print "."
        sleep 5
      end
      puts
    end

    def get_storage_info
      @storages = {}
      stats do |line|
        if /^storages\[(.+)\]\.storage\[(\d+)\]\.path\s(.+)/ =~ line
          @storages[$1] = [] unless @storages.key? $1
          @storages[$1][$2.to_i] = $3.chomp
#          puts "#{$1} #{$2} #{$3}"
        end
      end
    end

    def get_safecopy_stats(hname)
      ret = nil
      stats do |line|
        if /^storages\[#{hname}\]\.storage\.safecopy_stats\s(.+)/ =~ line
          ret = $1.chomp
        end
      end
      eval ret
    end

    def set_storage_status(hname, num, stat)
      @con.puts "set_storage_status #{num} #{stat} #{hname}\r\n"
      @con.gets
    end

    def set_gui_run_snapshot_status(status)
      @con.puts "set_gui_run_snapshot #{status}\r\n"
      @con.gets
    end

    def set_gui_last_snapshot
      t = Time.now.strftime('%Y/%m/%dT%H:%M:%S')
      @con.puts "set_gui_last_snapshot #{t}\r\n"
      @con.gets
    end

    def stats(regexp = "storage")
      @con.puts "stat #{regexp}\r\n"
      yield $_ while @con.gets != "END\r\n"
    end

    def close
      set_gui_run_snapshot_status('false')
      @con.close if @con
    end

  end # SafeCopy
end # Roma

if ARGV.length < 1
  puts File.basename(__FILE__) + " [port]"
  exit
end

sc = Roma::SafeCopy.new("localhost", ARGV[0].to_i)

begin
  sc.check_storage_type
  sc.backup_all
  sc.set_gui_last_snapshot
  puts "finished"
ensure
  sc.close
end