Class: OsCtld::Console::Console

Inherits:
TTY
  • Object
show all
Includes:
OsCtl::Lib::Utils::Exception
Defined in:
lib/osctld/console/console.rb

Overview

Special case for tty0 (/dev/console)

tty0 is opened on container start, at least when it's started by osctld. The tty is accessed using unix server socket created by the osctld container wrapper.

Instance Attribute Summary

Attributes inherited from TTY

#ct, #n, #tty_in_io, #tty_out_io, #tty_pid

Instance Method Summary collapse

Methods inherited from TTY

#add_client, #client_read, #close, #initialize, #opened?, #remove_client, #start, #sync, #tty_read, #tty_write, #wake, #watch_ios

Methods included from Utils::SwitchUser

#ct_attach, #ct_syscmd

Constructor Details

This class inherits a constructor from OsCtld::Console::TTY

Instance Method Details

#connect(pid, socket) ⇒ Object



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/osctld/console/console.rb', line 18

def connect(pid, socket)
  tries = 0

  begin
    c = UNIXSocket.new(socket)

  rescue Errno::ENOENT
    raise if tries >= (0.2 * 50 * 10) # try for 10 seconds
    tries += 1
    sleep(0.2)
    retry
  end

  sync do
    @opened = true
    self.tty_pid = pid
    self.tty_in_io = c
    self.tty_out_io = c
    wake
  end
end

#handle_ct_stop(ctrc) ⇒ Object (protected)



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
# File 'lib/osctld/console/console.rb', line 87

def handle_ct_stop(ctrc)
  Lxcfs::Scheduler.remove_ct(ctrc.ct) unless ctrc.reboot?

  if ctrc.aborted?
    log(:info, ctrc, 'Container was aborted, performing cleanup')
    recovery = Container::Recovery.new(ctrc.ct)
    recovery.cleanup_or_taint
  end

  if ctrc.destroy_dataset_on_stop?
    begin
      TrashBin.add_dataset(ctrc.pool, ctrc.dataset)
    rescue SystemCommandFailed => e
      log(:warn, ctrc, "Unable to trash dataset '#{ctrc.dataset}': #{e.message}")
    end
  end

  if ctrc.reboot?
    sleep(1)
    reboot_ct

  elsif ctrc.aborted?
    return

  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_stopObject (protected)



81
82
83
84
85
# File 'lib/osctld/console/console.rb', line 81

def handle_improper_ct_stop
  # In this scenario, it is possible that the veth-down hooks weren't
  # run either. Cleanup interfaces that may have been left behind.
  ct.netifs.take_down
end

#on_closeObject (protected)



41
42
43
44
45
# File 'lib/osctld/console/console.rb', line 41

def on_close
  if ct.state == :stopped
    on_ct_stop
  end
end

#on_ct_stopObject (protected)



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
# File 'lib/osctld/console/console.rb', line 47

def on_ct_stop
  ctrc = ct.get_past_run_conf

  CpuScheduler.unschedule_ct(ct)

  begin
    ct.update_hints
  rescue Exception => e
    log(:warn, ct, "Unable to update hints: #{e.message} (#{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

  if ctrc.aborted? \
     || ctrc.reboot? \
     || ctrc.lxcfs_worker \
     || (ct.ephemeral? && !ct.is_being_manipulated?) \
     || (ctrc && ctrc.destroy_dataset_on_stop?)
    # The current thread is used to handle the console and has to exit.
    # Manipulation must happen from another thread.
    t = Thread.new { handle_ct_stop(ctrc) }
    ThreadReaper.add(t, nil)
  end

  ct.forget_past_run_conf
end

#openObject



14
15
16
# File 'lib/osctld/console/console.rb', line 14

def open
  # Does nothing for tty0, it is opened automatically on ct start
end

#reboot_ctObject (protected)



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/osctld/console/console.rb', line 121

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,
      force: true,
      manipulation_lock: 'wait',
    )
  rescue CommandFailed => e
    log(:warn, ct, "Reboot failed: #{e.message}")

  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