Class: OsCtld::Container
- Inherits:
-
Object
- Object
- OsCtld::Container
- Includes:
- OsCtl::Lib::Utils::Log, OsCtl::Lib::Utils::System, Assets::Definition, Lockable, Manipulable, Utils::SwitchUser
- Defined in:
- lib/osctld/container.rb,
lib/osctld/container/hooks.rb
Defined Under Namespace
Modules: Hook, Hooks Classes: Builder, Importer, LxcConfig, RawConfigs, Recovery
Instance Attribute Summary collapse
-
#apparmor ⇒ Object
Returns the value of attribute apparmor.
-
#arch ⇒ Object
Returns the value of attribute arch.
-
#attrs ⇒ Object
Returns the value of attribute attrs.
-
#autostart ⇒ Object
Returns the value of attribute autostart.
-
#cgparams ⇒ Object
Returns the value of attribute cgparams.
-
#dataset ⇒ Object
Returns the value of attribute dataset.
-
#devices ⇒ Object
Returns the value of attribute devices.
-
#dist_network_configured ⇒ Object
protected
Returns the value of attribute dist_network_configured.
-
#distribution ⇒ Object
Returns the value of attribute distribution.
-
#dns_resolvers ⇒ Object
Returns the value of attribute dns_resolvers.
-
#ephemeral ⇒ Object
(also: #ephemeral?)
Returns the value of attribute ephemeral.
-
#group ⇒ Object
Returns the value of attribute group.
-
#hostname ⇒ Object
Returns the value of attribute hostname.
-
#id ⇒ Object
Returns the value of attribute id.
-
#init_cmd ⇒ Object
Returns the value of attribute init_cmd.
-
#init_pid ⇒ Object
Returns the value of attribute init_pid.
-
#lxc_config ⇒ Object
Returns the value of attribute lxc_config.
-
#mounted ⇒ Object
protected
Returns the value of attribute mounted.
-
#mounts ⇒ Object
Returns the value of attribute mounts.
-
#nesting ⇒ Object
Returns the value of attribute nesting.
-
#netifs ⇒ Object
Returns the value of attribute netifs.
-
#pool ⇒ Object
Returns the value of attribute pool.
-
#prlimits ⇒ Object
Returns the value of attribute prlimits.
-
#raw_configs ⇒ Object
readonly
Returns the value of attribute raw_configs.
-
#seccomp_profile ⇒ Object
Returns the value of attribute seccomp_profile.
-
#send_log ⇒ Object
Returns the value of attribute send_log.
-
#state ⇒ Object
Returns the value of attribute state.
-
#user ⇒ Object
Returns the value of attribute user.
-
#version ⇒ Object
Returns the value of attribute version.
Class Method Summary collapse
Instance Method Summary collapse
- #abs_apply_cgroup_path(subsystem) ⇒ Object
- #abs_cgroup_path(subsystem) ⇒ Object
- #assets ⇒ Object
- #base_cgroup_path ⇒ Object
- #can_dist_configure_network? ⇒ Boolean
- #can_start? ⇒ Boolean
- #cgroup_path ⇒ Object
- #chgrp(grp, missing_devices: nil) ⇒ Object
- #chown(user) ⇒ Object
-
#clone_from(ct, id, opts = {}) ⇒ Object
protected
Change the container so that it becomes a clone of `ct` with a different id.
- #close_send_log(save: true) ⇒ Object
- #config_path ⇒ Object
- #configure(distribution, version, arch) ⇒ Object
- #configure_bashrc ⇒ Object
- #current_state ⇒ Object
-
#datasets ⇒ Array<OsCtl::Lib::Zfs::Dataset>
Return a list of all container datasets.
- #default_init_cmd ⇒ Object protected
- #default_seccomp_profile ⇒ Object protected
- #dir ⇒ Object
- #dist_configure_network ⇒ Object
- #dist_configure_network? ⇒ Boolean
-
#dump_config ⇒ Object
Dump to config.
-
#dup(id, opts = {}) ⇒ Object
Duplicate the container with a different ID.
-
#each_dataset {|ds| ... } ⇒ Object
Iterate over all container datasets.
-
#export ⇒ Object
Export to clients.
- #format_init_cmd ⇒ Object
- #gid_map ⇒ Object
- #ident ⇒ Object
-
#initialize(pool, id, user = nil, group = nil, dataset = nil, opts = {}) ⇒ Container
constructor
A new instance of Container.
- #load_config_file(path = nil, **opts) ⇒ Object protected
- #load_config_hash(cfg, init_devices: true, dataset_cache: nil) ⇒ Object protected
- #load_config_string(str, **opts) ⇒ Object protected
- #log_path ⇒ Object
- #log_type ⇒ Object
- #lxc_dir(user: nil, group: nil) ⇒ Object
- #lxc_home(user: nil, group: nil) ⇒ Object
- #manipulation_resource ⇒ Object
-
#mount(force: false) ⇒ Object
Mount the container's dataset.
-
#mounted?(force: false) ⇒ Boolean
Check if the container's dataset is mounted.
- #open_send_log(role, token, opts = {}) ⇒ Object
-
#patch_config(new_config) ⇒ Object
Update keys/values from `new_config` in the container's config.
- #prlimit_set(name, soft, hard) ⇒ Object
- #prlimit_unset(name) ⇒ Object
- #reboot? ⇒ Boolean
- #reload_config ⇒ Object
- #replace_config(config) ⇒ Object
- #request_reboot ⇒ Object
- #root_host_gid ⇒ Object
- #root_host_uid ⇒ Object
- #rootfs ⇒ Object
- #running? ⇒ Boolean
- #runtime_rootfs ⇒ Object
- #save_config ⇒ Object
- #set(opts) ⇒ Object
- #starting ⇒ Object
- #stopped ⇒ Object
- #uid_map ⇒ Object
- #unset(opts) ⇒ Object
- #user_hook_script_dir ⇒ Object
Methods included from Utils::SwitchUser
Methods included from Assets::Definition
Methods included from Manipulable
#acquire_manipulation_lock, #init_manipulable, #is_being_manipulated?, #manipulate, #manipulated_by, #release_manipulation_lock
Methods included from Lockable
#exclusively, included, #inclusively, #init_lock, #lock, #unlock
Constructor Details
#initialize(pool, id, user = nil, group = nil, dataset = nil, opts = {}) ⇒ Container
Returns a new instance of Container.
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 78 79 80 81 82 |
# File 'lib/osctld/container.rb', line 40 def initialize(pool, id, user = nil, group = nil, dataset = nil, opts = {}) init_lock init_manipulable opts[:load] = true unless opts.has_key?(:load) @pool = pool @id = id @user = user @group = group @dataset = dataset @state = opts[:staged] ? :staged : :unknown @ephemeral = false @init_pid = nil @netifs = NetInterface::Manager.new(self) @cgparams = nil @devices = nil @prlimits = nil @mounts = nil @hostname = nil @dns_resolvers = nil @nesting = false @seccomp_profile = nil @apparmor = AppArmor.new(self) @lxc_config = Container::LxcConfig.new(self) @init_cmd = nil @raw_configs = Container::RawConfigs.new @attrs = Attributes.new @dist_network_configured = false if opts[:load] load_opts = { init_devices: !opts.has_key?(:devices) || opts[:devices], dataset_cache: opts[:dataset_cache], } if opts[:load_from] load_config_string(opts[:load_from], **load_opts) else load_config_file(config_path, **load_opts) end end end |
Instance Attribute Details
#apparmor ⇒ Object
Returns the value of attribute apparmor
21 22 23 |
# File 'lib/osctld/container.rb', line 21 def apparmor @apparmor end |
#arch ⇒ Object
Returns the value of attribute arch
21 22 23 |
# File 'lib/osctld/container.rb', line 21 def arch @arch end |
#attrs ⇒ Object
Returns the value of attribute attrs
21 22 23 |
# File 'lib/osctld/container.rb', line 21 def attrs @attrs end |
#autostart ⇒ Object
Returns the value of attribute autostart
21 22 23 |
# File 'lib/osctld/container.rb', line 21 def autostart @autostart end |
#cgparams ⇒ Object
Returns the value of attribute cgparams
21 22 23 |
# File 'lib/osctld/container.rb', line 21 def cgparams @cgparams end |
#dataset ⇒ Object
Returns the value of attribute dataset
21 22 23 |
# File 'lib/osctld/container.rb', line 21 def dataset @dataset end |
#devices ⇒ Object
Returns the value of attribute devices
21 22 23 |
# File 'lib/osctld/container.rb', line 21 def devices @devices end |
#dist_network_configured ⇒ Object (protected)
Returns the value of attribute dist_network_configured
656 657 658 |
# File 'lib/osctld/container.rb', line 656 def dist_network_configured @dist_network_configured end |
#distribution ⇒ Object
Returns the value of attribute distribution
21 22 23 |
# File 'lib/osctld/container.rb', line 21 def distribution @distribution end |
#dns_resolvers ⇒ Object
Returns the value of attribute dns_resolvers
21 22 23 |
# File 'lib/osctld/container.rb', line 21 def dns_resolvers @dns_resolvers end |
#ephemeral ⇒ Object Also known as: ephemeral?
Returns the value of attribute ephemeral
21 22 23 |
# File 'lib/osctld/container.rb', line 21 def ephemeral @ephemeral end |
#group ⇒ Object
Returns the value of attribute group
21 22 23 |
# File 'lib/osctld/container.rb', line 21 def group @group end |
#hostname ⇒ Object
Returns the value of attribute hostname
21 22 23 |
# File 'lib/osctld/container.rb', line 21 def hostname @hostname end |
#id ⇒ Object
Returns the value of attribute id
21 22 23 |
# File 'lib/osctld/container.rb', line 21 def id @id end |
#init_cmd ⇒ Object
Returns the value of attribute init_cmd
21 22 23 |
# File 'lib/osctld/container.rb', line 21 def init_cmd @init_cmd end |
#init_pid ⇒ Object
Returns the value of attribute init_pid
21 22 23 |
# File 'lib/osctld/container.rb', line 21 def init_pid @init_pid end |
#lxc_config ⇒ Object
Returns the value of attribute lxc_config
21 22 23 |
# File 'lib/osctld/container.rb', line 21 def lxc_config @lxc_config end |
#mounted ⇒ Object (protected)
Returns the value of attribute mounted
656 657 658 |
# File 'lib/osctld/container.rb', line 656 def mounted @mounted end |
#mounts ⇒ Object
Returns the value of attribute mounts
21 22 23 |
# File 'lib/osctld/container.rb', line 21 def mounts @mounts end |
#nesting ⇒ Object
Returns the value of attribute nesting
21 22 23 |
# File 'lib/osctld/container.rb', line 21 def nesting @nesting end |
#netifs ⇒ Object
Returns the value of attribute netifs
21 22 23 |
# File 'lib/osctld/container.rb', line 21 def netifs @netifs end |
#pool ⇒ Object
Returns the value of attribute pool
21 22 23 |
# File 'lib/osctld/container.rb', line 21 def pool @pool end |
#prlimits ⇒ Object
Returns the value of attribute prlimits
21 22 23 |
# File 'lib/osctld/container.rb', line 21 def prlimits @prlimits end |
#raw_configs ⇒ Object (readonly)
Returns the value of attribute raw_configs
21 22 23 |
# File 'lib/osctld/container.rb', line 21 def raw_configs @raw_configs end |
#seccomp_profile ⇒ Object
Returns the value of attribute seccomp_profile
21 22 23 |
# File 'lib/osctld/container.rb', line 21 def seccomp_profile @seccomp_profile end |
#send_log ⇒ Object
Returns the value of attribute send_log
21 22 23 |
# File 'lib/osctld/container.rb', line 21 def send_log @send_log end |
#state ⇒ Object
Returns the value of attribute state
21 22 23 |
# File 'lib/osctld/container.rb', line 21 def state @state end |
#user ⇒ Object
Returns the value of attribute user
21 22 23 |
# File 'lib/osctld/container.rb', line 21 def user @user end |
#version ⇒ Object
Returns the value of attribute version
21 22 23 |
# File 'lib/osctld/container.rb', line 21 def version @version end |
Class Method Details
.default_dataset(pool, id, dataset_cache: nil) ⇒ Object
16 17 18 19 |
# File 'lib/osctld/container.rb', line 16 def self.default_dataset(pool, id, dataset_cache: nil) name = File.join(pool.ct_ds, id) OsCtl::Lib::Zfs::Dataset.new(name, base: name, cache: dataset_cache) end |
Instance Method Details
#abs_apply_cgroup_path(subsystem) ⇒ Object
391 392 393 |
# File 'lib/osctld/container.rb', line 391 def abs_apply_cgroup_path(subsystem) File.join(CGroup::FS, CGroup.real_subsystem(subsystem), base_cgroup_path) end |
#abs_cgroup_path(subsystem) ⇒ Object
387 388 389 |
# File 'lib/osctld/container.rb', line 387 def abs_cgroup_path(subsystem) File.join(CGroup::FS, CGroup.real_subsystem(subsystem), cgroup_path) end |
#assets ⇒ Object
105 106 107 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 133 134 135 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 |
# File 'lib/osctld/container.rb', line 105 def assets define_assets do |add| # Datasets add.dataset( dataset, desc: "Container's rootfs dataset", uidmap: uid_map.map(&:to_a), gidmap: gid_map.map(&:to_a), user: root_host_uid, group: root_host_gid, mode: 0770, validate_if: mounted?, ) # Directories and files add.directory( rootfs, desc: "Container's rootfs", user: root_host_uid, group: root_host_gid, mode: 0755, validate_if: mounted?, ) add.directory( user_hook_script_dir, desc: 'User supplied script hooks', user: 0, group: 0, mode: 0700 ) add.directory( lxc_dir, desc: 'LXC configuration', user: 0, group: user.ugid, mode: 0750 ) lxc_config.assets(add) add.file( File.join(lxc_dir, '.bashrc'), desc: 'Shell configuration file for osctl ct su', user: 0, group: 0, mode: 0644 ) add.file( config_path, desc: 'Container config for osctld', user: 0, group: 0, mode: 0400 ) add.file( log_path, desc: 'LXC log file', user: 0, group: user.ugid, mode: 0660 ) end end |
#base_cgroup_path ⇒ Object
379 380 381 |
# File 'lib/osctld/container.rb', line 379 def base_cgroup_path inclusively { File.join(group.full_cgroup_path(user), "ct.#{id}") } end |
#can_dist_configure_network? ⇒ Boolean
292 293 294 295 296 297 |
# File 'lib/osctld/container.rb', line 292 def can_dist_configure_network? inclusively do next false if netifs.detect { |netif| !netif.can_run_distconfig? } true end end |
#can_start? ⇒ Boolean
270 271 272 |
# File 'lib/osctld/container.rb', line 270 def can_start? inclusively { state != :staged && state != :error && pool.active? } end |
#cgroup_path ⇒ Object
383 384 385 |
# File 'lib/osctld/container.rb', line 383 def cgroup_path File.join(base_cgroup_path, 'user-owned') end |
#chgrp(grp, missing_devices: nil) ⇒ Object
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
# File 'lib/osctld/container.rb', line 216 def chgrp(grp, missing_devices: nil) self.group = grp case missing_devices when 'provide' devices.ensure_all devices.create when 'remove' devices.remove_missing devices.create when 'check' devices.check_all_available!(grp) else fail "unsupported action for missing devices: '#{missing_devices}'" end save_config lxc_config.configure configure_bashrc end |
#chown(user) ⇒ Object
209 210 211 212 213 214 |
# File 'lib/osctld/container.rb', line 209 def chown(user) self.user = user save_config lxc_config.configure configure_bashrc end |
#clone_from(ct, id, opts = {}) ⇒ Object (protected)
Change the container so that it becomes a clone of `ct` with a different id
731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 |
# File 'lib/osctld/container.rb', line 731 def clone_from(ct, id, opts = {}) init_lock init_manipulable @id = id @pool = opts[:pool] if opts[:pool] @user = opts[:user] if opts[:user] @group = opts[:group] if opts[:group] @init_pid = nil @state = :staged @send_log = nil @do_reboot = false if opts[:dataset] @dataset = OsCtl::Lib::Zfs::Dataset.new( opts[:dataset], base: opts[:dataset], ) else @dataset = Container.default_dataset(@pool, @id) end @apparmor = @apparmor.dup(self) @autostart = @autostart && @autostart.dup(self) @cgparams = cgparams.dup(self) @prlimits = prlimits.dup(self) @mounts = mounts.dup(self) @lxc_config = lxc_config.dup(self) @raw_configs = raw_configs.dup @attrs = attrs.dup @devices = devices.dup(self) devices.init if opts[:network_interfaces] @netifs = netifs.dup(self) netifs.each(&:setup) else @netifs = NetInterface::Manager.new(self) end end |
#close_send_log(save: true) ⇒ Object
529 530 531 532 533 534 535 |
# File 'lib/osctld/container.rb', line 529 def close_send_log(save: true) exclusively do self.send_log.close self.send_log = nil save_config if save end end |
#config_path ⇒ Object
342 343 344 |
# File 'lib/osctld/container.rb', line 342 def config_path inclusively { File.join(pool.conf_path, 'ct', "#{id}.yml") } end |
#configure(distribution, version, arch) ⇒ Object
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/osctld/container.rb', line 88 def configure(distribution, version, arch) exclusively do @distribution = distribution @version = version @arch = arch @netifs = NetInterface::Manager.new(self) @nesting = false @seccomp_profile = default_seccomp_profile @cgparams = CGroup::ContainerParams.new(self) @devices = Devices::ContainerManager.new(self) @prlimits = PrLimits::Manager.default(self) @mounts = Mount::Manager.new(self) devices.init save_config end end |
#configure_bashrc ⇒ Object
509 510 511 512 513 514 515 516 517 518 519 520 |
# File 'lib/osctld/container.rb', line 509 def configure_bashrc ErbTemplate.render_to('ct/bashrc', { ct: self, override: %w( attach cgroup console device execute info ls monitor stop top wait ), disable: %w( autostart checkpoint clone copy create destroy freeze snapshot start-ephemeral unfreeze unshare ), }, File.join(lxc_dir, '.bashrc')) end |
#current_state ⇒ Object
258 259 260 261 262 263 264 |
# File 'lib/osctld/container.rb', line 258 def current_state begin self.state = ContainerControl::Commands::State.run!(self).state rescue ContainerControl::Error self.state = :error end end |
#datasets ⇒ Array<OsCtl::Lib::Zfs::Dataset>
Return a list of all container datasets
368 369 370 371 |
# File 'lib/osctld/container.rb', line 368 def datasets ds = inclusively { dataset } [ds] + ds.descendants end |
#default_init_cmd ⇒ Object (protected)
777 778 779 |
# File 'lib/osctld/container.rb', line 777 def default_init_cmd ['/sbin/init'] end |
#default_seccomp_profile ⇒ Object (protected)
773 774 775 |
# File 'lib/osctld/container.rb', line 773 def default_seccomp_profile '/etc/lxc/config/common.seccomp' end |
#dir ⇒ Object
312 313 314 |
# File 'lib/osctld/container.rb', line 312 def dir dataset.mountpoint end |
#dist_configure_network ⇒ Object
305 306 307 308 309 310 |
# File 'lib/osctld/container.rb', line 305 def dist_configure_network return unless dist_configure_network? DistConfig.run(self, :network) self.dist_network_configured = true end |
#dist_configure_network? ⇒ Boolean
299 300 301 302 303 |
# File 'lib/osctld/container.rb', line 299 def dist_configure_network? inclusively do !dist_network_configured && can_dist_configure_network? end end |
#dump_config ⇒ Object
Dump to config
570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 |
# File 'lib/osctld/container.rb', line 570 def dump_config inclusively do data = { 'user' => user.name, 'group' => group.name, 'dataset' => dataset.name, 'distribution' => distribution, 'version' => version, 'arch' => arch, 'net_interfaces' => netifs.dump, 'cgparams' => cgparams.dump, 'devices' => devices.dump, 'prlimits' => prlimits.dump, 'mounts' => mounts.dump, 'autostart' => autostart && autostart.dump, 'ephemeral' => ephemeral, 'hostname' => hostname && hostname.to_s, 'dns_resolvers' => dns_resolvers, 'nesting' => nesting, 'seccomp_profile' => seccomp_profile == default_seccomp_profile \ ? nil : seccomp_profile, 'init_cmd' => init_cmd, 'raw' => raw_configs.dump, 'attrs' => attrs.dump, } data['state'] = 'staged' if state == :staged data['send_log'] = send_log.dump if send_log data end end |
#dup(id, opts = {}) ⇒ Object
Duplicate the container with a different ID
The returned container has `state` set to `:staged` and its assets will not exist, so the caller has to build the container and call `ct.state = :complete` for the container to become usable.
183 184 185 186 187 |
# File 'lib/osctld/container.rb', line 183 def dup(id, opts = {}) ct = clone ct.send(:clone_from, self, id, opts) ct end |
#each_dataset {|ds| ... } ⇒ Object
Iterate over all container datasets
375 376 377 |
# File 'lib/osctld/container.rb', line 375 def each_dataset(&block) datasets.each(&block) end |
#export ⇒ Object
Export to clients
538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 |
# File 'lib/osctld/container.rb', line 538 def export inclusively do { pool: pool.name, id: id, user: user.name, group: group.name, dataset: dataset.name, rootfs: rootfs, lxc_path: lxc_home, lxc_dir: lxc_dir, group_path: cgroup_path, distribution: distribution, version: version, state: state, init_pid: init_pid, autostart: autostart ? true : false, autostart_priority: autostart && autostart.priority, autostart_delay: autostart && autostart.delay, ephemeral: ephemeral, hostname: hostname, dns_resolvers: dns_resolvers, nesting: nesting, seccomp_profile: seccomp_profile, init_cmd: format_init_cmd, raw_lxc: raw_configs.lxc, log_file: log_path, }.merge!(attrs.export) end end |
#format_init_cmd ⇒ Object
634 635 636 |
# File 'lib/osctld/container.rb', line 634 def format_init_cmd (init_cmd || default_init_cmd).join(' ') end |
#gid_map ⇒ Object
354 355 356 |
# File 'lib/osctld/container.rb', line 354 def gid_map user.gid_map end |
#ident ⇒ Object
84 85 86 |
# File 'lib/osctld/container.rb', line 84 def ident inclusively { "#{pool.name}:#{id}" } end |
#load_config_file(path = nil, **opts) ⇒ Object (protected)
658 659 660 |
# File 'lib/osctld/container.rb', line 658 def load_config_file(path = nil, **opts) load_config_hash(YAML.load_file(path || config_path), **opts) end |
#load_config_hash(cfg, init_devices: true, dataset_cache: nil) ⇒ Object (protected)
666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 |
# File 'lib/osctld/container.rb', line 666 def load_config_hash(cfg, init_devices: true, dataset_cache: nil) exclusively do @state = cfg['state'].to_sym if cfg['state'] @user ||= DB::Users.find(cfg['user'], pool) || (raise "user not found") @group ||= DB::Groups.find(cfg['group'], pool) || (raise "group not found") unless @dataset if cfg['dataset'] @dataset = OsCtl::Lib::Zfs::Dataset.new( cfg['dataset'], base: cfg['dataset'], cache: dataset_cache, ) else @dataset = Container.default_dataset( pool, id, dataset_cache: dataset_cache, ) end end @distribution = cfg['distribution'] @version = cfg['version'] @arch = cfg['arch'] @autostart = cfg['autostart'] && AutoStart::Config.load(self, cfg['autostart']) @ephemeral = cfg['ephemeral'] @hostname = cfg['hostname'] && OsCtl::Lib::Hostname.new(cfg['hostname']) @dns_resolvers = cfg['dns_resolvers'] @nesting = cfg['nesting'] || false @seccomp_profile = cfg['seccomp_profile'] || default_seccomp_profile @init_cmd = cfg['init_cmd'] if cfg['send_log'] @send_log = SendReceive::Log.load(cfg['send_log']) SendReceive::Tokens.register(@send_log.token) end @cgparams = CGroup::ContainerParams.load(self, cfg['cgparams']) @prlimits = PrLimits::Manager.load(self, cfg['prlimits'] || {}) @raw_configs = Container::RawConfigs.new(cfg['raw'] || {}) @attrs = Attributes.load(cfg['attrs'] || {}) # It's necessary to load devices _before_ netifs. The device manager needs # to create cgroups first, in order for echo a > devices.deny to work. # If the container has a veth interface, the setup code switches to the # container's user, which creates cgroups in all subsystems. Devices then # can't be initialized properly. @devices = Devices::ContainerManager.load(self, cfg['devices'] || []) @devices.init if init_devices @netifs = NetInterface::Manager.load(self, cfg['net_interfaces'] || []) @mounts = Mount::Manager.load(self, cfg['mounts'] || []) end end |
#load_config_string(str, **opts) ⇒ Object (protected)
662 663 664 |
# File 'lib/osctld/container.rb', line 662 def load_config_string(str, **opts) load_config_hash(YAML.load(str), **opts) end |
#log_path ⇒ Object
638 639 640 |
# File 'lib/osctld/container.rb', line 638 def log_path inclusively { File.join(pool.log_path, 'ct', "#{id}.log") } end |
#log_type ⇒ Object
642 643 644 |
# File 'lib/osctld/container.rb', line 642 def log_type inclusively { "ct=#{pool.name}:#{id}" } end |
#lxc_dir(user: nil, group: nil) ⇒ Object
320 321 322 |
# File 'lib/osctld/container.rb', line 320 def lxc_dir(user: nil, group: nil) inclusively { File.join(lxc_home(user: user, group: group), id) } end |
#lxc_home(user: nil, group: nil) ⇒ Object
316 317 318 |
# File 'lib/osctld/container.rb', line 316 def lxc_home(user: nil, group: nil) inclusively { (group || self.group).userdir(user || self.user) } end |
#manipulation_resource ⇒ Object
646 647 648 |
# File 'lib/osctld/container.rb', line 646 def manipulation_resource ['container', ident] end |
#mount(force: false) ⇒ Object
Mount the container's dataset
192 193 194 195 196 |
# File 'lib/osctld/container.rb', line 192 def mount(force: false) return if !force && mounted dataset.mount(recursive: true) self.mounted = true end |
#mounted?(force: false) ⇒ Boolean
Check if the container's dataset is mounted
201 202 203 204 205 206 207 |
# File 'lib/osctld/container.rb', line 201 def mounted?(force: false) if force || mounted.nil? self.mounted = dataset.mounted?(recursive: true) else mounted end end |
#open_send_log(role, token, opts = {}) ⇒ Object
522 523 524 525 526 527 |
# File 'lib/osctld/container.rb', line 522 def open_send_log(role, token, opts = {}) exclusively do self.send_log = SendReceive::Log.new(role: role, token: token, opts: opts) save_config end end |
#patch_config(new_config) ⇒ Object
Update keys/values from `new_config` in the container's config
625 626 627 628 629 630 631 632 |
# File 'lib/osctld/container.rb', line 625 def patch_config(new_config) exclusively do tmp = dump_config tmp.update(new_config) load_config_hash(tmp) save_config end end |
#prlimit_set(name, soft, hard) ⇒ Object
482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 |
# File 'lib/osctld/container.rb', line 482 def prlimit_set(name, soft, hard) exclusively do limit = @prlimits.detect { |v| v.name == name } if limit limit.set(soft, hard) else @prlimits << PrLimit.new(name, soft, hard) end end save_config lxc_config.configure end |
#prlimit_unset(name) ⇒ Object
498 499 500 501 502 503 504 505 506 507 |
# File 'lib/osctld/container.rb', line 498 def prlimit_unset(name) exclusively do limit = @prlimits.detect { |v| v.name == name } next unless limit @prlimits.delete(limit) end save_config lxc_config.configure_prlimits end |
#reboot? ⇒ Boolean
288 289 290 |
# File 'lib/osctld/container.rb', line 288 def reboot? @do_reboot end |
#reload_config ⇒ Object
613 614 615 |
# File 'lib/osctld/container.rb', line 613 def reload_config load_config_file end |
#replace_config(config) ⇒ Object
618 619 620 621 |
# File 'lib/osctld/container.rb', line 618 def replace_config(config) load_config_string(config) save_config end |
#request_reboot ⇒ Object
284 285 286 |
# File 'lib/osctld/container.rb', line 284 def request_reboot @do_reboot = true end |
#root_host_gid ⇒ Object
362 363 364 |
# File 'lib/osctld/container.rb', line 362 def root_host_gid user.gid_map.ns_to_host(0) end |
#root_host_uid ⇒ Object
358 359 360 |
# File 'lib/osctld/container.rb', line 358 def root_host_uid user.uid_map.ns_to_host(0) end |
#rootfs ⇒ Object
324 325 326 327 328 329 330 331 |
# File 'lib/osctld/container.rb', line 324 def rootfs File.join(dir, 'private') rescue SystemCommandFailed # Dataset for staged containers does not have to exist yet, relevant # primarily for ct show/list nil end |
#running? ⇒ Boolean
266 267 268 |
# File 'lib/osctld/container.rb', line 266 def running? state == :running end |
#runtime_rootfs ⇒ Object
333 334 335 336 337 338 339 340 |
# File 'lib/osctld/container.rb', line 333 def runtime_rootfs fail 'container is not running' unless running? pid = inclusively { init_pid } fail 'init_pid not set' unless pid File.join('/proc', pid.to_s, 'root') end |
#save_config ⇒ Object
603 604 605 606 607 608 609 610 611 |
# File 'lib/osctld/container.rb', line 603 def save_config data = dump_config File.open(config_path, 'w', 0400) do |f| f.write(YAML.dump(data)) end File.chown(0, 0, config_path) end |
#set(opts) ⇒ Object
395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 |
# File 'lib/osctld/container.rb', line 395 def set(opts) opts.each do |k, v| case k when :autostart self.autostart = AutoStart::Config.new(self, v[:priority], v[:delay]) when :ephemeral self.ephemeral = true when :hostname original = nil exclusively do original = @hostname @hostname = OsCtl::Lib::Hostname.new(v) end DistConfig.run(self, :set_hostname, original: original) when :dns_resolvers self.dns_resolvers = v DistConfig.run(self, :dns_resolvers) when :nesting self.nesting = true when :distribution exclusively do @distribution = v[:name] @version = v[:version] @arch = v[:arch] if v[:arch] end when :seccomp_profile self.seccomp_profile = v when :init_cmd self.init_cmd = v when :raw_lxc self.raw_configs.lxc = v when :attrs attrs.update(v) end end save_config lxc_config.configure_base end |
#starting ⇒ Object
274 275 276 277 |
# File 'lib/osctld/container.rb', line 274 def starting self.dist_network_configured = false @do_reboot = false end |
#stopped ⇒ Object
279 280 281 282 |
# File 'lib/osctld/container.rb', line 279 def stopped self.dist_network_configured = false self.init_pid = nil end |
#uid_map ⇒ Object
350 351 352 |
# File 'lib/osctld/container.rb', line 350 def uid_map user.uid_map end |
#unset(opts) ⇒ Object
446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 |
# File 'lib/osctld/container.rb', line 446 def unset(opts) opts.each do |k, v| case k when :autostart self.autostart = false when :ephemeral self.ephemeral = false when :hostname self.hostname = nil when :dns_resolvers self.dns_resolvers = nil when :nesting self.nesting = false when :seccomp_profile self.seccomp_profile = default_seccomp_profile when :init_cmd self.init_cmd = nil when :raw_lxc self.raw_configs.lxc = nil when :attrs v.each { |attr| attrs.unset(attr) } end end save_config lxc_config.configure_base end |
#user_hook_script_dir ⇒ Object
346 347 348 |
# File 'lib/osctld/container.rb', line 346 def user_hook_script_dir inclusively { File.join(pool.user_hook_script_dir, 'ct', id) } end |