Class: OsCtld::Container::StopHandler
- Inherits:
-
Object
- Object
- OsCtld::Container::StopHandler
- Includes:
- OsCtl::Lib::Utils::Exception, OsCtl::Lib::Utils::Log
- Defined in:
- lib/osctld/container/stop_handler.rb
Overview
The same exit cleanup for console-managed and direct LXC starts.
Instance Attribute Summary collapse
-
#ct ⇒ Object
readonly
Returns the value of attribute ct.
Class Method Summary collapse
Instance Method Summary collapse
- #handle_ct_stop(ctrc) ⇒ Object protected
- #handle_improper_ct_stop ⇒ Object protected
-
#initialize(ct, run_conf = nil) ⇒ StopHandler
constructor
A new instance of StopHandler.
- #reboot_ct ⇒ Object protected
- #run ⇒ Object
Constructor Details
#initialize(ct, run_conf = nil) ⇒ StopHandler
Returns a new instance of StopHandler.
16 17 18 19 |
# File 'lib/osctld/container/stop_handler.rb', line 16 def initialize(ct, run_conf = nil) @ct = ct @run_conf = run_conf end |
Instance Attribute Details
#ct ⇒ Object (readonly)
Returns the value of attribute ct.
14 15 16 |
# File 'lib/osctld/container/stop_handler.rb', line 14 def ct @ct end |
Class Method Details
.schedule(ct, run_conf = nil) ⇒ Object
9 10 11 12 |
# File 'lib/osctld/container/stop_handler.rb', line 9 def self.schedule(ct, run_conf = nil) thread = Thread.new { new(ct, run_conf).run } ThreadReaper.add(thread, nil) end |
Instance Method Details
#handle_ct_stop(ctrc) ⇒ Object (protected)
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/osctld/container/stop_handler.rb', line 81 def handle_ct_stop(ctrc) if ctrc.aborted? log(:info, ctrc, 'Container was aborted, performing cleanup') recovery = Container::Recovery.new(ctrc.ct) recovery.cleanup_or_taint end if !ct.ephemeral? && !ctrc.destroy_dataset_on_stop? && Daemon.get.config.writeout_dirtied_pages? # Force write-out of dirtied pages force_mount = false begin ct.unmount(force: true) rescue SystemCommandFailed => e log(:warn, ctrc, "Unable to unmount dataset for writeback: #{e.}") force_mount = true end ct.mount(force: force_mount) end if ctrc.destroy_dataset_on_stop? GarbageCollector.free_container_run_dataset(ctrc, ctrc.dataset) end ctrc.fulfil_exit if ctrc.reboot? sleep(1) reboot_ct elsif ctrc.aborted? nil elsif ct.ephemeral? && !ct.is_being_manipulated? Commands::Container::Delete.run( pool: ct.pool.name, id: ct.id, force: true, manipulation_lock: 'wait' ) end end |
#handle_improper_ct_stop ⇒ Object (protected)
74 75 76 77 78 79 |
# File 'lib/osctld/container/stop_handler.rb', line 74 def handle_improper_ct_stop # In this scenario, it is possible that the veth-down hooks weren't # run either. Use the same all-record preflight and durable taint gate as # forced deletion; never perform an unchecked direct teardown. Container::Recovery.new(ct).cleanup_or_taint end |
#reboot_ct ⇒ Object (protected)
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/osctld/container/stop_handler.rb', line 125 def reboot_ct ct.pool.request_reboot(ct) until ct.pool.imported? log(:info, ct, 'Waiting for pool import to reboot') sleep(1) end begin ret = Commands::Container::Start.run( pool: ct.pool.name, id: ct.id, manipulation_lock: 'wait' ) rescue CommandFailed => e log(:warn, ct, "Reboot failed: #{e.}") else if !ret.is_a?(Hash) log(:warn, ct, 'Reboot failed: reason unknown') elsif !ret[:status] log(:warn, ct, "Reboot failed: #{ret[:message]}") end end end |
#run ⇒ Object
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 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 |
# File 'lib/osctld/container/stop_handler.rb', line 21 def run # The TTY may have closed due to an unforeseen error, check if the # container is actually stopped. 60.times do break if ct.state == :stopped log(:info, ct, 'Exit handler waiting for stopped state') sleep(1) end unless ct.state == :stopped log(:fatal, ct, 'Exit handler ran, but container is not stopped') return end ctrc = @run_conf || ct.get_past_run_conf return if @run_conf && !ct.get_past_run_conf.equal?(@run_conf) return if ctrc && !ctrc.claim_exit_handling CpuScheduler.unschedule_ct(ct) begin ct.update_hints rescue Exception => e # rubocop:disable Lint/RescueException log(:warn, ct, "Unable to update hints: #{e.} (#{e.class})") log(:warn, ct, denixstorify(e.backtrace)) end if ctrc.nil? # This means that {UserControl::Commands::CtPostStop} hasn't run for some # reason. log(:fatal, ct, 'Unable to properly handle container stop') handle_improper_ct_stop return end # Send events about halt/reboot from the inside if !ctrc.aborted? && !ct.is_being_manipulated? Eventd.report( :ct_exit, pool: ct.pool.name, id: ct.id, exit_type: ctrc.reboot? ? 'reboot' : 'halt' ) end handle_ct_stop(ctrc) ct.forget_past_run_conf(ctrc) end |