Class: OsCtl::Cli::Bisect
- Inherits:
-
Object
- Object
- OsCtl::Cli::Bisect
- Defined in:
- lib/osctl/cli/bisect.rb
Instance Attribute Summary collapse
-
#cols ⇒ Object
readonly
protected
Returns the value of attribute cols.
-
#cts ⇒ Object
readonly
protected
Returns the value of attribute cts.
-
#mutex ⇒ Object
readonly
protected
Returns the value of attribute mutex.
-
#suspend_action ⇒ Object
readonly
protected
Returns the value of attribute suspend_action.
Instance Method Summary collapse
- #action_reverse(action) ⇒ Object protected
- #action_str(action) ⇒ Object protected
- #ask_confirmation! ⇒ Object protected
- #ask_success? ⇒ Boolean protected
- #bisect ⇒ Object protected
- #execute_action_set(ct_set, action) ⇒ Object protected
-
#initialize(cts, suspend_action: nil, cols: nil) ⇒ Bisect
constructor
A new instance of Bisect.
- #print_set(ct_set) ⇒ Object protected
- #reset ⇒ Object
- #run ⇒ Object
Constructor Details
#initialize(cts, suspend_action: nil, cols: nil) ⇒ Bisect
Returns a new instance of Bisect.
8 9 10 11 12 13 14 |
# File 'lib/osctl/cli/bisect.rb', line 8 def initialize(cts, suspend_action: nil, cols: nil) @cts = cts @suspend_action = suspend_action @cols = cols @mutex = Mutex.new @last_manifested = true end |
Instance Attribute Details
#cols ⇒ Object (readonly, protected)
Returns the value of attribute cols.
40 41 42 |
# File 'lib/osctl/cli/bisect.rb', line 40 def cols @cols end |
#cts ⇒ Object (readonly, protected)
Returns the value of attribute cts.
40 41 42 |
# File 'lib/osctl/cli/bisect.rb', line 40 def cts @cts end |
#mutex ⇒ Object (readonly, protected)
Returns the value of attribute mutex.
40 41 42 |
# File 'lib/osctl/cli/bisect.rb', line 40 def mutex @mutex end |
#suspend_action ⇒ Object (readonly, protected)
Returns the value of attribute suspend_action.
40 41 42 |
# File 'lib/osctl/cli/bisect.rb', line 40 def suspend_action @suspend_action end |
Instance Method Details
#action_reverse(action) ⇒ Object (protected)
178 179 180 |
# File 'lib/osctl/cli/bisect.rb', line 178 def action_reverse(action) action == :suspend ? :resume : :suspend end |
#action_str(action) ⇒ Object (protected)
182 183 184 185 186 187 188 189 190 |
# File 'lib/osctl/cli/bisect.rb', line 182 def action_str(action) if suspend_action == :freeze action == :suspend ? 'freeze' : 'thaw' elsif suspend_action == :stop action == :suspend ? 'stop' : 'start' else raise "invalid action '#{suspend_action}'" end end |
#ask_confirmation! ⇒ Object (protected)
97 98 99 100 101 102 103 104 105 106 |
# File 'lib/osctl/cli/bisect.rb', line 97 def ask_confirmation! $stdout.write('Continue? [y/N]: ') $stdout.flush unless %w[y yes].include?($stdin.readline.strip.downcase) raise 'Aborted' end puts end |
#ask_success? ⇒ Boolean (protected)
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/osctl/cli/bisect.rb', line 108 def ask_success? loop do $stdout.write('Is the issue manifesting? [y/n]: ') $stdout.flush s = $stdin.readline.strip.downcase ret = nil # rubocop:disable Style/NegatedIfElseCondition if %w[y yes].include?(s) ret = !@last_manifested ? true : false @last_manifested = true elsif %w[n no].include?(s) ret = @last_manifested ? true : false @last_manifested = false end # rubocop:enable Style/NegatedIfElseCondition puts return ret unless ret.nil? end end |
#bisect ⇒ Object (protected)
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/osctl/cli/bisect.rb', line 42 def bisect ct_set = @cts.clone action = :suspend loop do if ct_set.size == 1 execute_action_set(ct_set, :resume) if action == :resume ct = ct_set.first puts puts "Container identified: #{ct[:pool]}:#{ct[:id]}" break end left, right = ct_set.each_slice((ct_set.size / 2.0).round).to_a execute_action_set(left, action) puts if action == :suspend if ask_success? ct_set = left action = :resume execute_action_set(right, :resume) else ct_set = right action = :suspend execute_action_set(left, :resume) puts end elsif action == :resume if ask_success? ct_set = left action = :suspend execute_action_set(right, :resume) else ct_set = right action = :resume execute_action_set(left, :resume) puts end else raise 'programming error' end puts "Narrowed down to #{ct_set.size} containers" end end |
#execute_action_set(ct_set, action) ⇒ Object (protected)
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/osctl/cli/bisect.rb', line 136 def execute_action_set(ct_set, action) queue = Queue.new ct_set.each_with_index { |ct, i| queue << [i + 1, ct] } n = ct_set.length osctl_action = if suspend_action == :freeze action == :suspend ? :ct_freeze : :ct_unfreeze elsif suspend_action == :stop action == :suspend ? :ct_stop : :ct_start else raise "invalid action '#{suspend_action}'" end threads = Etc.nprocessors.times.map do Thread.new do c = OsCtl::Client.new c.open loop do begin i, ct = queue.pop(true) rescue ThreadError break end resp = c.cmd_response(osctl_action, pool: ct[:pool], id: ct[:id]) mutex.synchronize do puts "[#{i}/#{n}] #{action_str(action)} #{ct[:pool]}:#{ct[:id]} " \ "... #{resp.ok? ? 'ok' : "error: #{resp.}"}" end end c.close end end threads.each(&:join) end |
#print_set(ct_set) ⇒ Object (protected)
93 94 95 |
# File 'lib/osctl/cli/bisect.rb', line 93 def print_set(ct_set) OsCtl::Lib::Cli::OutputFormatter.print(ct_set, cols:, layout: :columns) end |
#reset ⇒ Object
34 35 36 |
# File 'lib/osctl/cli/bisect.rb', line 34 def reset execute_action_set(cts, :resume) end |
#run ⇒ Object
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
# File 'lib/osctl/cli/bisect.rb', line 16 def run print_set(cts) puts puts "Selected containers: #{cts.length}" puts "Suspend action: #{suspend_action}" puts ask_confirmation! begin bisect rescue StandardError, Interrupt puts puts 'Resuming all affected containers...' reset raise end end |