module OfflineServicesScript

Require all replication services to be OFFLINE before proceeding with the main() method. The user can add –offline to have this done for them, and –online to bring them back ONLINE when the script finishes cleanly.

Public Instance Methods

allow_service_state_change?() click to toggle source
# File lib/tungsten/script.rb, line 860
def allow_service_state_change?
  if TI == nil
    return false
  end

  if TI.is_replicator?() && TI.is_running?("replicator")
    true
  else
    false
  end
end
cleanup(code = 0) click to toggle source
Calls superclass method
# File lib/tungsten/script.rb, line 748
def cleanup(code = 0)
  if initialized?() == true && TI != nil && code == 0
    begin
      clear_logs = opt(:clear_logs)
      if clear_logs_during_prepare() == true
        clear_logs = false
      end
      
      if allow_service_state_change?() == true && @options[:online] == true
        cleanup_services(true, clear_logs)
      elsif clear_logs == true
        cleanup_services(false, clear_logs)
      end
    rescue => e
      TU.exception(e)
      code = 1
    end
  end
  
  super(code)
end
cleanup_services(online = false, clear_logs = false) click to toggle source
# File lib/tungsten/script.rb, line 770
def cleanup_services(online = false, clear_logs = false)
  ds_list = get_offline_services_list()

  # Put each replication service ONLINE in parallel waiting for the
  # command to complete
  if online == true
    TU.notice("Put the #{ds_list.join(",")} replication #{TU.pluralize(ds_list, "service", "services")} online")
  end
  
  # Emptying the THL and relay logs makes sure that we are starting with
  # a fresh directory as if `datasource <hostname> restore` was run.
  if clear_logs == true
    TU.notice("Clear THL and relay logs for the #{ds_list.join(",")} replication #{TU.pluralize(ds_list, "service", "services")}")
  end
  
  threads = []
  begin
    Timeout::timeout(@options[:offline_timeout]) {
      ds_list.each{
        |ds|
        threads << Thread.new{
          if clear_logs == true
            dir = TI.setting(TI.setting_key(REPL_SERVICES, ds, "repl_thl_directory"))
            if File.exists?(dir)
              TU.cmd_result("rm -rf #{dir}/*")
            end
            dir = TI.setting(TI.setting_key(REPL_SERVICES, ds, "repl_relay_directory"))
            if File.exists?(dir)
              TU.cmd_result("rm -rf #{dir}/*")
            end
          end
          
          if online == true
            use_manager = false
            
            if TI.is_manager?()
              status = TI.status(ds)
              
              # Make sure this is actually a physical dataservice
              if status.is_physical?()
                # Does this datasource actually appear in the status
                # It may not if the host hasn't been provisioned
                if status.datasources().index(TI.hostname()) != nil
                  use_manager = true
                end
              end
            end
            
            begin
              if use_manager == true
                # Bring the replicator and the datasource ONLINE
                TU.cmd_result("echo 'datasource #{TI.hostname()} recover' | #{TI.cctrl()}")
              else
                # Bring just the replicator ONLINE
                TU.cmd_result("#{TI.trepctl(ds)} online")
              end
            rescue => e
              TU.exception(e)
              raise("The #{ds} replication service did not come online")
            end
            
            # Verify the replicator is in fact ONLINE since the recover
            # command may have not returned the right error
            unless TI.trepctl_value(ds, "state") == "ONLINE"
              raise("Unable to put the #{ds} replication service online")
            end
          end
        }
      }

      threads.each{|t| t.join() }
    }
  rescue Timeout::Error
    TU.error("The replication #{TU.pluralize(ds_list, "service", "services")} #{TU.pluralize(ds_list, "is", "are")} taking too long to cleanup. Check the replicator status for more information.")
  end
end
clear_logs_during_prepare() click to toggle source
# File lib/tungsten/script.rb, line 880
def clear_logs_during_prepare
  false
end
configure() click to toggle source
Calls superclass method
# File lib/tungsten/script.rb, line 626
def configure
  super()
  
  add_option(:clear_logs, {
    :on => "--clear-logs",
    :default => false,
    :help => "Delete all THL and relay logs for the service"
  })
  
  add_option(:offline, {
    :on => "--offline [String]",
    :help => "Put required replication services offline before processing",
    :default => false,
    :parse => method(:parse_boolean_option_blank_is_true)
  })
  
  add_option(:offline_timeout, {
    :on => "--offline-timeout Integer",
    :help => "Put required replication services offline before processing",
    :parse => method(:parse_integer_option),
    :default => 60
  })
  
  add_option(:online, {
    :on => "--online [String]",
    :help => "Put required replication services online after successful processing",
    :default => false,
    :parse => method(:parse_boolean_option_blank_is_true)
  })
end
get_manager_api() click to toggle source
# File lib/tungsten/script.rb, line 872
def get_manager_api
  if @api == nil && TI != nil
    @api = TungstenAPI::TungstenDataserviceManager.new(TI.mgr_api_uri())
  end
  
  @api
end
get_offline_services_list() click to toggle source

All replication services must be OFFLINE

# File lib/tungsten/script.rb, line 848
def get_offline_services_list
  TI.replication_services()
end
prepare() click to toggle source
Calls superclass method
# File lib/tungsten/script.rb, line 677
def prepare
  super()
  
  if TU.is_valid?()
    begin
      if allow_service_state_change?() == true && @options[:offline] == true
        ds_list = get_offline_services_list()
        
        # Put each replication service OFFLINE in parallel waiting for the
        # command to complete
        TU.notice("Put #{ds_list.join(",")} replication #{TU.pluralize(ds_list, "service", "services")} offline")
        
        threads = []
        begin
          Timeout::timeout(@options[:offline_timeout]) {
            ds_list.each{
              |ds|
              threads << Thread.new{
                use_manager = false
                
                if TI.is_manager?()
                  status = TI.status(ds)
                  
                  # Make sure this is actually a physical dataservice
                  if status.is_physical?()
                    # Does this datasource actually appear in the status
                    # It may not if the host hasn't been provisioned
                    if status.datasources().index(TI.hostname()) != nil
                      use_manager = true
                    end
                  end
                end
                
                begin
                  if use_manager == true
                    TU.cmd_result("echo 'datasource #{TI.hostname()} shun' | #{TI.cctrl()}")
                  end
                
                  # The trepctl offline command is required even when using
                  # the manager because shun doesn't affect the replicator
                  TU.cmd_result("#{TI.trepctl(ds)} offline")
                rescue => e
                  TU.exception(e)
                  raise("Unable to put replication services offline")
                end
              }
            }
            threads.each{|t| t.join() }
          }
        rescue Timeout::Error
          raise("The replication #{TU.pluralize(ds_list, "service", "services")} #{TU.pluralize(ds_list, "is", "are")} taking too long to go offline. Check the status for more information or use the --offline-timeout argument.")
        end
      end
    end
    
    begin
      clear_logs = opt(:clear_logs)
      if clear_logs_during_prepare() == false
        clear_logs = false
      end
      
      if clear_logs == true
        cleanup_services(false, clear_logs)
      end
    rescue => e
      TU.exception(e)
      code = 1
    end
  end
end
require_offline_services?() click to toggle source
# File lib/tungsten/script.rb, line 852
def require_offline_services?
  if @options[:offline] == true
    false
  else
    true
  end
end
validate() click to toggle source
Calls superclass method
# File lib/tungsten/script.rb, line 657
def validate
  super()
  
  # Some scripts may disable the OFFLINE requirement depending on other
  # arguments. These methods give them hooks to make that decision dynamic.
  if allow_service_state_change?() && require_offline_services?()
    # Check the state of each replication service
    get_offline_services_list().each{
      |ds|
      if TI.trepctl_value(ds, "state") =~ /ONLINE/
        TU.error("The replication service '#{ds}' must be OFFLINE to run this command. You can add the --offline argument to do this automatically.")
      end
    }
  end
  
  unless @options[:offline_timeout] > 0
    TU.error("The --offline-timeout must be a number greater than zero")
  end
end