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)


860
861
862
863
864
865
866
867
868
869
870
# 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) ⇒ Object



748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
# 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) ⇒ Object



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
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
# 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_prepareObject



880
881
882
# File 'lib/tungsten/script.rb', line 880

def clear_logs_during_prepare
  false
end

#configureObject



626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
# 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_apiObject



872
873
874
875
876
877
878
# 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_listObject

All replication services must be OFFLINE



848
849
850
# File 'lib/tungsten/script.rb', line 848

def get_offline_services_list
  TI.replication_services()
end

#prepareObject



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
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
# 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?Boolean

Returns:

  • (Boolean)


852
853
854
855
856
857
858
# File 'lib/tungsten/script.rb', line 852

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

#validateObject



657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
# 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