Class: OsCtld::DistConfig::Distributions::Base
- Inherits:
-
Object
- Object
- OsCtld::DistConfig::Distributions::Base
- Includes:
- OsCtl::Lib::Utils::Log, OsCtl::Lib::Utils::System, Utils::SwitchUser
- Defined in:
- lib/osctld/dist_config/distributions/base.rb
Instance Attribute Summary collapse
-
#configurator ⇒ Object
readonly
protected
Returns the value of attribute configurator.
-
#ct ⇒ Object
readonly
Returns the value of attribute ct.
-
#ctrc ⇒ Object
readonly
Returns the value of attribute ctrc.
-
#distribution ⇒ Object
readonly
Returns the value of attribute distribution.
-
#version ⇒ Object
readonly
Returns the value of attribute version.
Class Method Summary collapse
Instance Method Summary collapse
-
#add_netif(opts) ⇒ Object
Called when a new network interface is added to a container.
-
#apply_hostname ⇒ Object
Configure hostname in a running system.
-
#bin_path(_opts) ⇒ String
Return path to ‘/bin` or an alternative, where a shell is looked up.
- #configurator_class ⇒ Object
- #dns_resolvers(_opts = {}) ⇒ Object
-
#initialize(ctrc) ⇒ Base
constructor
A new instance of Base.
- #log_type ⇒ Object
- #network(_opts = {}) ⇒ Object
- #passwd(opts) ⇒ Object
-
#post_mount(opts) ⇒ Object
Called by LXC post-mount hook on container start.
-
#pre_start(_opts = {}) ⇒ Object
Called before container start, can be used to e.g.
-
#remove_netif(opts) ⇒ Object
Called when a network interface is removed from a container.
-
#rename_netif(opts) ⇒ Object
Called when an existing network interface is renamed.
-
#set_hostname(opts = {}) ⇒ Object
Set container hostname.
-
#start(_opts = {}) ⇒ Object
Run just before the container is started.
-
#stop(opts) ⇒ Object
Gracefully stop the container.
-
#unset_etc_hosts(_opts = {}) ⇒ Object
Remove the osctld-generated notice from /etc/hosts.
-
#update_etc_hosts(opts = {}) ⇒ Object
Update hostname in ‘/etc/hosts`, optionally removing configuration of old hostname.
-
#volatile_is_systemd? ⇒ Boolean
protected
Check if the container is using systemd as init.
- #with_rootfs(&block) ⇒ Object protected
Methods included from Utils::SwitchUser
Constructor Details
#initialize(ctrc) ⇒ Base
Returns a new instance of Base.
21 22 23 24 25 26 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 21 def initialize(ctrc) @ctrc = ctrc @ct = ctrc.ct @distribution = ctrc.distribution @version = ctrc.version end |
Instance Attribute Details
#configurator ⇒ Object (readonly, protected)
Returns the value of attribute configurator.
243 244 245 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 243 def configurator @configurator end |
#ct ⇒ Object (readonly)
Returns the value of attribute ct.
18 19 20 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 18 def ct @ct end |
#ctrc ⇒ Object (readonly)
Returns the value of attribute ctrc.
18 19 20 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 18 def ctrc @ctrc end |
#distribution ⇒ Object (readonly)
Returns the value of attribute distribution.
18 19 20 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 18 def distribution @distribution end |
#version ⇒ Object (readonly)
Returns the value of attribute version.
18 19 20 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 18 def version @version end |
Class Method Details
.distribution(n = nil) ⇒ Object
10 11 12 13 14 15 16 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 10 def self.distribution(n = nil) if n DistConfig.register(n, self) else n end end |
Instance Method Details
#add_netif(opts) ⇒ Object
Called when a new network interface is added to a container
183 184 185 186 187 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 183 def add_netif(opts) with_rootfs do configurator.add_netif(ct.netifs, opts[:netif]) end end |
#apply_hostname ⇒ Object
Configure hostname in a running system
152 153 154 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 152 def apply_hostname log(:warn, ct, "Unable to apply hostname on #{distribution}: not implemented") end |
#bin_path(_opts) ⇒ String
Return path to ‘/bin` or an alternative, where a shell is looked up
233 234 235 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 233 def bin_path(_opts) '/bin' end |
#configurator_class ⇒ Object
28 29 30 31 32 33 34 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 28 def configurator_class raise "define #{self.class}#configurator_class" unless self.class.const_defined?(:Configurator) cls = self.class::Configurator log(:debug, "Using #{cls} for #{ctrc.distribution}") cls end |
#dns_resolvers(_opts = {}) ⇒ Object
208 209 210 211 212 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 208 def dns_resolvers(_opts = {}) with_rootfs do configurator.dns_resolvers(ct.dns_resolvers) end end |
#log_type ⇒ Object
237 238 239 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 237 def log_type ct.id end |
#network(_opts = {}) ⇒ Object
174 175 176 177 178 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 174 def network(_opts = {}) with_rootfs do configurator.network(ct.netifs) end end |
#passwd(opts) ⇒ Object
217 218 219 220 221 222 223 224 225 226 227 228 229 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 217 def passwd(opts) ret = ct_syscmd( ct, %w[chpasswd], stdin: "#{opts[:user]}:#{opts[:password]}\n", run: true, valid_rcs: :all ) return true if ret.success? log(:warn, ct, "Unable to set password: #{ret.output}") end |
#post_mount(opts) ⇒ Object
Called by LXC post-mount hook on container start
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 80 def post_mount(opts) return unless volatile_is_systemd? ContainerControl::Commands::WithMountns.run!( ct, ns_pid: opts[:ns_pid], chroot: opts[:rootfs_mount], block: proc do # /run is mounted by {#pre_start} FileUtils.mkdir_p('/run/udev') # Create /run/udev/control if it isn't already there begin File.stat('/run/udev/control') rescue Errno::ENOENT File.new('/run/udev/control', 'w').close end true end ) end |
#pre_start(_opts = {}) ⇒ Object
Called before container start, can be used to e.g. add temporary mounts
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 71 72 73 74 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 37 def pre_start(_opts = {}) return unless volatile_is_systemd? # systemd by default does not monitor udev events in containers, which # means that there are no device units to depend on, e.g. for network # interfaces. systemd decides this by the existence of socket # /run/udev/control and that /dev is devtmpfs. Our /dev cannot be # devtmpfs since that doesn't work in containers, and /run/udev/control # is created by a socket unit *after* systemd makes the decision to not # monitor udev events. After `systemctl daemon-reload`, it actually # starts to monitor udev events and the device units are created. # # See https://github.com/systemd/systemd/blob/729d2df8065ac90ac606e1fff91dc2d588b2795d/src/libsystemd/sd-device/device-monitor.c#L125 # # We therefore mount /run as tmpfs before systemd is run and create # a stub for /run/udev/control, so that the check passes and udev events # are monitored from the start. # # /run has to be mounted by LXC from the container's user namespace, so # that it is owned by that user namespace. File /run/udev/control is # created later in {#post_mount}. # Check if /run isn't mounted already by user configuration return unless ct.mounts.detect { |mnt| %w[/run /run/].include?(mnt.mountpoint) }.nil? mem_limit = ct.find_memory_limit mnt_opts = %w[nosuid nodev mode=755 create=dir] mnt_opts << "size=#{mem_limit / 2}" if mem_limit ct.mounts.add(Mount::Entry.new( 'tmpfs', '/run', 'tmpfs', mnt_opts.join(','), false, temp: true, in_config: true )) end |
#remove_netif(opts) ⇒ Object
Called when a network interface is removed from a container
192 193 194 195 196 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 192 def remove_netif(opts) with_rootfs do configurator.remove_netif(ct.netifs, opts[:netif]) end end |
#rename_netif(opts) ⇒ Object
Called when an existing network interface is renamed
202 203 204 205 206 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 202 def rename_netif(opts) with_rootfs do configurator.rename_netif(ct.netifs, opts[:netif], opts[:original_name]) end end |
#set_hostname(opts = {}) ⇒ Object
Set container hostname
142 143 144 145 146 147 148 149 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 142 def set_hostname(opts = {}) with_rootfs do configurator.set_hostname(ct.hostname, old_hostname: opts[:original]) configurator.update_etc_hosts(ct.hostname, old_hostname: opts[:original]) end apply_hostname if ct.running? end |
#start(_opts = {}) ⇒ Object
Run just before the container is started
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 104 def start(_opts = {}) return unless ct.hostname || ct.dns_resolvers || ctrc.dist_configure_network? net_configured = with_rootfs do ret = false set_hostname if ct.hostname dns_resolvers if ct.dns_resolvers if ctrc.dist_configure_network? network ret = true end ret end ctrc.dist_network_configured = true if net_configured end |
#stop(opts) ⇒ Object
Gracefully stop the container
129 130 131 132 133 134 135 136 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 129 def stop(opts) ContainerControl::Commands::Stop.run!( ct, opts[:mode], message: opts[:message], timeout: opts[:timeout] ) end |
#unset_etc_hosts(_opts = {}) ⇒ Object
Remove the osctld-generated notice from /etc/hosts
168 169 170 171 172 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 168 def unset_etc_hosts(_opts = {}) with_rootfs do configurator.unset_etc_hosts end end |
#update_etc_hosts(opts = {}) ⇒ Object
Update hostname in ‘/etc/hosts`, optionally removing configuration of old hostname.
161 162 163 164 165 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 161 def update_etc_hosts(opts = {}) with_rootfs do configurator.update_etc_hosts(ct.hostname, old_hostname: opts[:old_hostname]) end end |
#volatile_is_systemd? ⇒ Boolean (protected)
Check if the container is using systemd as init
This method accesses the container’s rootfs from the host, which is dangerous because of symlinks and we really shouldn’t be doing it… but in this case, we only do readlink(), so it shouldn’t do any harm.
273 274 275 276 277 278 279 280 281 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 273 def volatile_is_systemd? return true if ctrc.distribution == 'nixos' begin File.readlink(File.join(ctrc.rootfs, 'sbin/init')).include?('systemd') rescue SystemCallError false end end |
#with_rootfs(&block) ⇒ Object (protected)
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 245 def with_rootfs(&block) if @within_rootfs block.call else ContainerControl::Commands::WithRootfs.run!( ctrc.ct, ctrc:, block: proc do @configurator = configurator_class.new( ct.id, '/', ct.distribution, ct.version ) @within_rootfs = true block.call end ) end end |