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
Run 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.
244 245 246 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 244 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
186 187 188 189 190 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 186 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
155 156 157 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 155 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
235 236 237 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 235 def bin_path(_opts) '/bin' end |
#configurator_class ⇒ Object
28 29 30 31 32 33 34 35 36 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 28 def configurator_class if self.class.const_defined?(:Configurator) cls = self.class::Configurator log(:debug, "Using #{cls} for #{ctrc.distribution}") cls else fail "define #{self.class}#configurator_class" end end |
#dns_resolvers(_opts = {}) ⇒ Object
211 212 213 214 215 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 211 def dns_resolvers(_opts = {}) with_rootfs do configurator.dns_resolvers(ct.dns_resolvers) end end |
#log_type ⇒ Object
239 240 241 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 239 def log_type ct.id end |
#network(_opts = {}) ⇒ Object
177 178 179 180 181 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 177 def network(_opts = {}) with_rootfs do configurator.network(ct.netifs) end end |
#passwd(opts) ⇒ Object
220 221 222 223 224 225 226 227 228 229 230 231 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 220 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
Run by LXC post-mount hook on container start
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 83 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.new 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.open('/run/udev/control', 'w') {} end true end, ) end |
#pre_start(opts = {}) ⇒ Object
Called before container start, can be used to e.g. add temporary mounts
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 75 76 77 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 39 def pre_start(opts = {}) if 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 if 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 end end |
#remove_netif(opts) ⇒ Object
Called when a network interface is removed from a container
195 196 197 198 199 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 195 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
205 206 207 208 209 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 205 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
145 146 147 148 149 150 151 152 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 145 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
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 107 def start(opts = {}) if 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 end |
#stop(opts) ⇒ Object
Gracefully stop the container
132 133 134 135 136 137 138 139 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 132 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
171 172 173 174 175 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 171 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.
164 165 166 167 168 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 164 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.
274 275 276 277 278 279 280 281 282 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 274 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)
246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 |
# File 'lib/osctld/dist_config/distributions/base.rb', line 246 def with_rootfs(&block) if @within_rootfs block.call else ContainerControl::Commands::WithRootfs.run!( ctrc.ct, ctrc: ctrc, block: Proc.new do @configurator = configurator_class.new( ct.id, '/', ct.distribution, ct.version, ) @within_rootfs = true block.call end, ) end end |