Module: OfflineServicesScript

Included in:
OfflineSingleServiceScript
Defined in:
lib/tungsten/script.rb

Overview

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.

Instance Method Summary collapse

Instance Method Details

#allow_service_state_change?Boolean

Returns:

  • (Boolean)


824
825
826
827
828
829
830
831
832
833
834
# File 'lib/tungsten/script.rb', line 824

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) ⇒ Object



717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
# File 'lib/tungsten/script.rb', line 717

def cleanup(code = 0)
  if initialized?() == true && TI != nil && code == 0
    begin
      if allow_service_state_change?() == true && @options[:online] == true
        cleanup_services(true, @options[:clear_logs])
      elsif @options[:clear_logs] == true
        cleanup_services(false, @options[:clear_logs])
      end
    rescue => e
      TU.exception(e)
      code = 1
    end
  end
  
  super(code)
end

#cleanup_services(online = false, clear_logs = false) ⇒ Object



734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
# File 'lib/tungsten/script.rb', line 734

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

#configureObject



607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
# File 'lib/tungsten/script.rb', line 607

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_apiObject



836
837
838
839
840
841
842
# File 'lib/tungsten/script.rb', line 836

def get_manager_api
  if @api == nil && TI != nil
    @api = TungstenAPI::TungstenDataserviceManager.new(TI.mgr_api_uri())
  end
  
  @api
end

#get_offline_services_listObject

All replication services must be OFFLINE



812
813
814
# File 'lib/tungsten/script.rb', line 812

def get_offline_services_list
  TI.replication_services()
end

#prepareObject



658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
# File 'lib/tungsten/script.rb', line 658

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
                    get_manager_api.call("#{ds}/#{TI.hostname()}", 'shun')
                  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
    rescue => e
      TU.exception(e)
    end
  end
end

#require_offline_services?Boolean

Returns:

  • (Boolean)


816
817
818
819
820
821
822
# File 'lib/tungsten/script.rb', line 816

def require_offline_services?
  if @options[:offline] == true
    false
  else
    true
  end
end

#validateObject



638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
# File 'lib/tungsten/script.rb', line 638

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