confctl 2.0.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +19 -1
- data/Gemfile +6 -0
- data/README.md +2 -1
- data/docs/carrier.md +12 -0
- data/lib/confctl/cli/app.rb +19 -0
- data/lib/confctl/cli/cluster.rb +183 -47
- data/lib/confctl/cli/generation.rb +44 -15
- data/lib/confctl/cli/swpins/channel.rb +6 -4
- data/lib/confctl/cli/swpins/cluster.rb +6 -4
- data/lib/confctl/cli/swpins/core.rb +6 -4
- data/lib/confctl/generation/build.rb +42 -1
- data/lib/confctl/generation/build_list.rb +10 -0
- data/lib/confctl/generation/host.rb +9 -5
- data/lib/confctl/generation/host_list.rb +20 -5
- data/lib/confctl/generation/unified.rb +5 -0
- data/lib/confctl/generation/unified_list.rb +10 -0
- data/lib/confctl/machine.rb +4 -0
- data/lib/confctl/machine_control.rb +3 -2
- data/lib/confctl/machine_list.rb +4 -0
- data/lib/confctl/machine_status.rb +1 -1
- data/lib/confctl/nix.rb +63 -18
- data/lib/confctl/nix_copy.rb +5 -5
- data/lib/confctl/null_logger.rb +7 -0
- data/lib/confctl/swpins/change_set.rb +11 -4
- data/lib/confctl/swpins/specs/git.rb +23 -16
- data/lib/confctl/swpins/specs/git_rev.rb +1 -1
- data/lib/confctl/system_command.rb +3 -2
- data/lib/confctl/version.rb +1 -1
- data/libexec/auto-rollback.rb +106 -0
- data/man/man8/confctl.8 +109 -72
- data/man/man8/confctl.8.md +91 -54
- data/nix/evaluator.nix +26 -1
- data/nix/modules/cluster/default.nix +20 -0
- data/nix/modules/confctl/carrier/base.nix +8 -6
- data/nix/modules/confctl/carrier/netboot/build-netboot-server.rb +209 -50
- data/nix/modules/confctl/carrier/netboot/nixos.nix +5 -3
- data/nix/modules/confctl/kexec-netboot/default.nix +38 -0
- data/nix/modules/confctl/kexec-netboot/kexec-netboot.8.adoc +62 -0
- data/nix/modules/confctl/kexec-netboot/kexec-netboot.rb +455 -0
- data/nix/modules/confctl/overlays.nix +15 -0
- data/nix/modules/module-list.nix +1 -0
- data/nix/modules/system-list.nix +3 -1
- data/shell.nix +9 -2
- metadata +8 -6
data/nix/evaluator.nix
CHANGED
@@ -81,7 +81,32 @@ let
|
|
81
81
|
abort "Attribute 'config.${coreLib.concatStringsSep "." machine.build.attribute}' not found on machine ${machine.name}"
|
82
82
|
else
|
83
83
|
buildAttr;
|
84
|
-
in
|
84
|
+
in {
|
85
|
+
attribute = result;
|
86
|
+
|
87
|
+
autoRollback =
|
88
|
+
# pkgs.substituteAll was removed from nixos-unstable, but pkgs.replaceVarsWith
|
89
|
+
# is not available in nixos-25.05.
|
90
|
+
let
|
91
|
+
args = {
|
92
|
+
src = ../libexec/auto-rollback.rb;
|
93
|
+
isExecutable = true;
|
94
|
+
};
|
95
|
+
|
96
|
+
replacements = {
|
97
|
+
ruby = nixpkgs.ruby;
|
98
|
+
};
|
99
|
+
in
|
100
|
+
if builtins.hasAttr "replaceVarsWith" corePkgs then
|
101
|
+
corePkgs.replaceVarsWith {
|
102
|
+
inherit (args) src isExecutable;
|
103
|
+
inherit replacements;
|
104
|
+
}
|
105
|
+
else
|
106
|
+
corePkgs.substituteAll ({
|
107
|
+
inherit (args) src isExecutable;
|
108
|
+
} // replacements);
|
109
|
+
};
|
85
110
|
|
86
111
|
evalMachine = machine:
|
87
112
|
let
|
@@ -186,6 +186,26 @@ let
|
|
186
186
|
};
|
187
187
|
};
|
188
188
|
|
189
|
+
autoRollback = {
|
190
|
+
enable = mkOption {
|
191
|
+
type = types.bool;
|
192
|
+
default = true;
|
193
|
+
description = ''
|
194
|
+
Enable automatic rollback in case the machine is unresponsive after
|
195
|
+
deploy
|
196
|
+
'';
|
197
|
+
};
|
198
|
+
|
199
|
+
timeout = mkOption {
|
200
|
+
type = types.int;
|
201
|
+
default = 60;
|
202
|
+
description = ''
|
203
|
+
Number of seconds after which if the machine is unreachable, auto-rollback
|
204
|
+
is initiated
|
205
|
+
'';
|
206
|
+
};
|
207
|
+
};
|
208
|
+
|
189
209
|
healthChecks = {
|
190
210
|
systemd = {
|
191
211
|
enable = mkOption {
|
@@ -4,16 +4,18 @@ let
|
|
4
4
|
|
5
5
|
cfg = config.confctl.carrier;
|
6
6
|
|
7
|
-
carrier-env = pkgs.
|
7
|
+
carrier-env = pkgs.confReplaceVarsWith {
|
8
8
|
src = ./carrier-env.rb;
|
9
9
|
name = "carrier-env";
|
10
10
|
isExecutable = true;
|
11
11
|
dir = "bin";
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
replacements = {
|
13
|
+
ruby = pkgs.ruby;
|
14
|
+
onChangeCommands = pkgs.writeScript "carrier-on-change-commands.sh" ''
|
15
|
+
#!${pkgs.bash}/bin/bash
|
16
|
+
${cfg.onChangeCommands}
|
17
|
+
'';
|
18
|
+
};
|
17
19
|
};
|
18
20
|
in {
|
19
21
|
options = {
|
@@ -166,7 +166,7 @@ class NetbootBuilder
|
|
166
166
|
|
167
167
|
link_path = File.join(LINK_DIR, v)
|
168
168
|
|
169
|
-
machines[name] ||= Machine.new(name)
|
169
|
+
machines[name] ||= Machine.new(@config, name)
|
170
170
|
machines[name].add_generation(link_path, generation)
|
171
171
|
end
|
172
172
|
|
@@ -255,6 +255,12 @@ class RootBuilder
|
|
255
255
|
FileUtils.mkdir_p(File.join(root, v))
|
256
256
|
end
|
257
257
|
end
|
258
|
+
|
259
|
+
# Create a file within root
|
260
|
+
def write_to(path, content)
|
261
|
+
mkdir_p(File.dirname(path))
|
262
|
+
File.write(File.join(root, path), content)
|
263
|
+
end
|
258
264
|
end
|
259
265
|
|
260
266
|
class TftpBuilder < RootBuilder
|
@@ -301,10 +307,10 @@ class TftpBuilder < RootBuilder
|
|
301
307
|
path = File.join('boot', m.fqdn, g.generation.to_s)
|
302
308
|
mkdir_p(path)
|
303
309
|
|
304
|
-
|
305
|
-
next unless %w[bzImage initrd].include?(
|
310
|
+
g.boot_files.each_value do |boot_file|
|
311
|
+
next unless %w[bzImage initrd].include?(boot_file.name)
|
306
312
|
|
307
|
-
ln_s(
|
313
|
+
ln_s(boot_file.path, File.join(path, boot_file.name))
|
308
314
|
end
|
309
315
|
|
310
316
|
ln_s(g.generation.to_s, File.join('boot', m.fqdn, 'current')) if g.current
|
@@ -432,7 +438,7 @@ class TftpBuilder < RootBuilder
|
|
432
438
|
|
433
439
|
<% m.generations[1..].each do |g| -%>
|
434
440
|
LABEL <%= m.fqdn %>-<%= g.generation %>
|
435
|
-
MENU LABEL
|
441
|
+
MENU LABEL Gen <%= g.generation %> - <%= g.time_s %> - <%= g.shortrev %>
|
436
442
|
LINUX boot/<%= m.fqdn %>/<%= g.generation %>/bzImage
|
437
443
|
INITRD boot/<%= m.fqdn %>/<%= g.generation %>/initrd
|
438
444
|
APPEND init=<%= g.toplevel %>/init loglevel=7
|
@@ -496,47 +502,19 @@ class TftpBuilder < RootBuilder
|
|
496
502
|
# @param root [Boolean] true if this is machine menu page, not generation menu
|
497
503
|
# @param timeout [Integer, nil] timeout in seconds until the default action is taken
|
498
504
|
def render_machine_vpsadminos_config(machine, generation:, file:, root:, timeout: nil)
|
499
|
-
variants = {
|
500
|
-
default: {
|
501
|
-
label: 'Default runlevel',
|
502
|
-
kernel_params: [],
|
503
|
-
runlevel: 'default'
|
504
|
-
},
|
505
|
-
nopools: {
|
506
|
-
label: 'Default runlevel without container imports',
|
507
|
-
kernel_params: ['osctl.pools=0'],
|
508
|
-
runlevel: 'default'
|
509
|
-
},
|
510
|
-
nostart: {
|
511
|
-
label: 'Default runlevel without container autostart',
|
512
|
-
kernel_params: ['osctl.autostart=0'],
|
513
|
-
runlevel: 'default'
|
514
|
-
},
|
515
|
-
rescue: {
|
516
|
-
label: 'Rescue runlevel (network and sshd)',
|
517
|
-
kernel_params: [],
|
518
|
-
runlevel: 'rescue'
|
519
|
-
},
|
520
|
-
single: {
|
521
|
-
label: 'Single-user runlevel (console only)',
|
522
|
-
kernel_params: [],
|
523
|
-
runlevel: 'single'
|
524
|
-
}
|
525
|
-
}
|
526
|
-
|
527
505
|
tpl = <<~ERB
|
528
506
|
<% if timeout -%>
|
529
507
|
DEFAULT menu.c32
|
530
508
|
TIMEOUT 50
|
531
509
|
<% end -%>
|
532
|
-
MENU TITLE <%= m.
|
510
|
+
MENU TITLE <%= m.short_label %> (<%= g.generation %> - <%= g.current ? 'current' : g.time_s %> - <%= g.shortrev %> - <%= g.kernel_version %>)
|
533
511
|
|
534
|
-
<% variants.each do |variant
|
535
|
-
LABEL <%= variant %>
|
536
|
-
MENU LABEL <%=
|
512
|
+
<% g.variants.each do |variant| -%>
|
513
|
+
LABEL <%= variant.name %>
|
514
|
+
MENU LABEL <%= variant.label %>
|
537
515
|
LINUX boot/<%= m.fqdn %>/<%= g.generation %>/bzImage
|
538
516
|
INITRD boot/<%= m.fqdn %>/<%= g.generation %>/initrd
|
539
|
-
APPEND
|
517
|
+
APPEND <%= g.kernel_params.join(' ') %> <%= variant.kernel_params.join(' ') %>
|
540
518
|
|
541
519
|
<% end -%>
|
542
520
|
LABEL <%= m.fqdn %>-generations
|
@@ -562,7 +540,6 @@ class TftpBuilder < RootBuilder
|
|
562
540
|
{
|
563
541
|
m: machine,
|
564
542
|
g: generation,
|
565
|
-
variants:,
|
566
543
|
http_url: @config.http_url,
|
567
544
|
root:,
|
568
545
|
timeout:,
|
@@ -579,7 +556,7 @@ class TftpBuilder < RootBuilder
|
|
579
556
|
|
580
557
|
<% m.generations.each do |g| -%>
|
581
558
|
LABEL generations
|
582
|
-
MENU LABEL
|
559
|
+
MENU LABEL Gen <%= g.generation %> - <%= g.time_s %> - <%= g.shortrev %> - <%= g.kernel_version %>
|
583
560
|
KERNEL menu.c32
|
584
561
|
APPEND pxeserver/machines/<%= m.fqdn %>/generation-<%= g.generation %>.cfg
|
585
562
|
|
@@ -640,19 +617,23 @@ class HttpBuilder < RootBuilder
|
|
640
617
|
def build
|
641
618
|
machines.each do |m|
|
642
619
|
m.generations.each do |g|
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
620
|
+
gen_path = File.join(m.fqdn, g.generation.to_s)
|
621
|
+
mkdir_p(gen_path)
|
622
|
+
|
623
|
+
g.boot_files.each_value do |boot_file|
|
624
|
+
ln_s(boot_file.path, File.join(gen_path, boot_file.name))
|
647
625
|
end
|
648
626
|
|
649
|
-
|
627
|
+
write_to(File.join(gen_path, 'generation.json'), JSON.pretty_generate(g))
|
628
|
+
write_to(File.join(gen_path, 'kernel-params'), g.kernel_params.join(' '))
|
650
629
|
|
651
|
-
mkdir_p(gen_path)
|
652
|
-
ln_s(rootfs, File.join(gen_path, 'root.squashfs'))
|
653
630
|
ln_s(g.generation.to_s, File.join(m.fqdn, 'current')) if g.current
|
654
631
|
end
|
632
|
+
|
633
|
+
write_to(File.join(m.fqdn, 'machine.json'), JSON.pretty_generate(m))
|
655
634
|
end
|
635
|
+
|
636
|
+
write_to('machines.json', JSON.pretty_generate({ machines: }))
|
656
637
|
end
|
657
638
|
end
|
658
639
|
|
@@ -669,18 +650,27 @@ class Machine
|
|
669
650
|
# @return [String]
|
670
651
|
attr_reader :label
|
671
652
|
|
653
|
+
# @return [String]
|
654
|
+
attr_reader :short_label
|
655
|
+
|
656
|
+
# @return [String]
|
657
|
+
attr_reader :url
|
658
|
+
|
672
659
|
# @return [Array<Generation>]
|
673
660
|
attr_reader :generations
|
674
661
|
|
675
662
|
# @return [Generation]
|
676
663
|
attr_reader :current
|
677
664
|
|
665
|
+
# @param config [Config]
|
678
666
|
# @param name [String] machine name
|
679
|
-
def initialize(name)
|
667
|
+
def initialize(config, name)
|
668
|
+
@config = config
|
680
669
|
@name = name
|
681
670
|
@spin = 'nixos'
|
682
671
|
@fqdn = name
|
683
672
|
@label = name
|
673
|
+
@short_label = name[0..14]
|
684
674
|
@toplevel = nil
|
685
675
|
@macs = []
|
686
676
|
@generations = []
|
@@ -690,13 +680,29 @@ class Machine
|
|
690
680
|
# @param link_path [String] Nix store path
|
691
681
|
# @param generation [Integer]
|
692
682
|
def add_generation(link_path, generation)
|
693
|
-
@generations << Generation.new(link_path, generation)
|
683
|
+
@generations << Generation.new(self, link_path, generation)
|
694
684
|
nil
|
695
685
|
end
|
696
686
|
|
697
687
|
def resolve
|
698
688
|
sort_generations
|
699
689
|
load_json
|
690
|
+
|
691
|
+
@url = File.join(@config.http_url, fqdn)
|
692
|
+
generations.each(&:resolve)
|
693
|
+
|
694
|
+
nil
|
695
|
+
end
|
696
|
+
|
697
|
+
def to_json(*args)
|
698
|
+
{
|
699
|
+
url:,
|
700
|
+
name:,
|
701
|
+
spin:,
|
702
|
+
fqdn:,
|
703
|
+
label:,
|
704
|
+
generations:
|
705
|
+
}.to_json(*args)
|
700
706
|
end
|
701
707
|
|
702
708
|
protected
|
@@ -722,10 +728,15 @@ class Machine
|
|
722
728
|
@label ||= @current.json.fetch('fqdn', nil)
|
723
729
|
@label ||= name
|
724
730
|
# rubocop:enable Naming/MemoizedInstanceVariableName
|
731
|
+
|
732
|
+
@short_label = @label.split('.')[0..1].join('.')
|
725
733
|
end
|
726
734
|
end
|
727
735
|
|
728
736
|
class Generation
|
737
|
+
# @return [Machine]
|
738
|
+
attr_reader :machine
|
739
|
+
|
729
740
|
# @return [String]
|
730
741
|
attr_reader :link_path
|
731
742
|
|
@@ -741,9 +752,18 @@ class Generation
|
|
741
752
|
# @return [String]
|
742
753
|
attr_reader :time_s
|
743
754
|
|
755
|
+
# @return [String]
|
756
|
+
attr_reader :kernel_version
|
757
|
+
|
744
758
|
# @return [Array<String>]
|
745
759
|
attr_reader :kernel_params
|
746
760
|
|
761
|
+
# @return [Hash<String, BootFile>]
|
762
|
+
attr_reader :boot_files
|
763
|
+
|
764
|
+
# @return [Array<Variant>]
|
765
|
+
attr_reader :variants
|
766
|
+
|
747
767
|
# @return [String] Nix store path to `config.system.build.toplevel`
|
748
768
|
attr_reader :toplevel
|
749
769
|
|
@@ -765,9 +785,14 @@ class Generation
|
|
765
785
|
# @return [Hash] contents of `machine.json`
|
766
786
|
attr_reader :json
|
767
787
|
|
788
|
+
# @return [String]
|
789
|
+
attr_reader :url
|
790
|
+
|
791
|
+
# @param machine [Machine]
|
768
792
|
# @param link_path [String] Nix store path
|
769
793
|
# @param generation [Integer]
|
770
|
-
def initialize(link_path, generation)
|
794
|
+
def initialize(machine, link_path, generation)
|
795
|
+
@machine = machine
|
771
796
|
@link_path = link_path
|
772
797
|
@store_path = File.realpath(link_path)
|
773
798
|
@generation = generation
|
@@ -789,6 +814,8 @@ class Generation
|
|
789
814
|
|
790
815
|
@macs = json.fetch('macs', [])
|
791
816
|
|
817
|
+
@kernel_version = extract_kernel_version
|
818
|
+
|
792
819
|
kernel_params_file = File.join(store_path, 'kernel-params')
|
793
820
|
|
794
821
|
@kernel_params =
|
@@ -798,6 +825,138 @@ class Generation
|
|
798
825
|
json.fetch('kernelParams', [])
|
799
826
|
end
|
800
827
|
end
|
828
|
+
|
829
|
+
def resolve
|
830
|
+
@url = File.join(machine.url, generation.to_s)
|
831
|
+
@boot_files = find_boot_files
|
832
|
+
@variants = Variant.for_machine(machine)
|
833
|
+
|
834
|
+
return if machine.spin != 'vpsadminos'
|
835
|
+
|
836
|
+
@kernel_params.insert(0, "httproot=#{boot_files['root.squashfs'].url}")
|
837
|
+
end
|
838
|
+
|
839
|
+
def to_json(*args)
|
840
|
+
{
|
841
|
+
url:,
|
842
|
+
store_path:,
|
843
|
+
generation:,
|
844
|
+
time: time.to_i,
|
845
|
+
time_s:,
|
846
|
+
current:,
|
847
|
+
toplevel:,
|
848
|
+
version:,
|
849
|
+
revision:,
|
850
|
+
shortrev:,
|
851
|
+
macs:,
|
852
|
+
kernel_version:,
|
853
|
+
kernel_params:,
|
854
|
+
boot_files:,
|
855
|
+
variants:,
|
856
|
+
swpins_info: json['swpins-info']
|
857
|
+
}.to_json(*args)
|
858
|
+
end
|
859
|
+
|
860
|
+
protected
|
861
|
+
|
862
|
+
def extract_kernel_version
|
863
|
+
link = File.readlink(File.join(toplevel, 'kernel'))
|
864
|
+
return unless %r{\A/nix/store/[^-]+-linux-([^/]+)} =~ link
|
865
|
+
|
866
|
+
::Regexp.last_match(1)
|
867
|
+
rescue Errno::ENOENT
|
868
|
+
nil
|
869
|
+
end
|
870
|
+
|
871
|
+
def find_boot_files
|
872
|
+
%w[bzImage initrd root.squashfs].to_h do |name|
|
873
|
+
[name, BootFile.new(name, File.realpath(File.join(link_path, name)), File.join(url, name))]
|
874
|
+
rescue Errno::ENOENT
|
875
|
+
[name, nil]
|
876
|
+
end.compact
|
877
|
+
end
|
878
|
+
end
|
879
|
+
|
880
|
+
class BootFile
|
881
|
+
# @return [String]
|
882
|
+
attr_reader :name
|
883
|
+
|
884
|
+
# @return [String]
|
885
|
+
attr_reader :path
|
886
|
+
|
887
|
+
# @return [String]
|
888
|
+
attr_reader :url
|
889
|
+
|
890
|
+
def initialize(name, path, url)
|
891
|
+
@name = name
|
892
|
+
@path = path
|
893
|
+
@url = url
|
894
|
+
end
|
895
|
+
|
896
|
+
def to_json(*args)
|
897
|
+
url.to_json(*args)
|
898
|
+
end
|
899
|
+
end
|
900
|
+
|
901
|
+
class Variant
|
902
|
+
# @param machine [Machine]
|
903
|
+
# @return [Array<Variant>]
|
904
|
+
def self.for_machine(machine)
|
905
|
+
if machine.spin == 'vpsadminos'
|
906
|
+
[
|
907
|
+
new(
|
908
|
+
name: 'default',
|
909
|
+
label: 'Default runlevel',
|
910
|
+
kernel_params: ['runlevel=default']
|
911
|
+
),
|
912
|
+
new(
|
913
|
+
name: 'nopools',
|
914
|
+
label: 'Default runlevel without container imports',
|
915
|
+
kernel_params: ['runlevel=default', 'osctl.pools=0']
|
916
|
+
),
|
917
|
+
new(
|
918
|
+
name: 'nostart',
|
919
|
+
label: 'Default runlevel without container autostart',
|
920
|
+
kernel_params: ['runlevel=default', 'osctl.autostart=0']
|
921
|
+
),
|
922
|
+
new(
|
923
|
+
name: 'rescue',
|
924
|
+
label: 'Rescue runlevel (network and sshd)',
|
925
|
+
kernel_params: ['runlevel=rescue']
|
926
|
+
),
|
927
|
+
new(
|
928
|
+
name: 'single',
|
929
|
+
label: 'Single-user runlevel (console only)',
|
930
|
+
kernel_params: ['runlevel=single']
|
931
|
+
)
|
932
|
+
]
|
933
|
+
else
|
934
|
+
[]
|
935
|
+
end
|
936
|
+
end
|
937
|
+
|
938
|
+
# @return [String]
|
939
|
+
attr_reader :name
|
940
|
+
|
941
|
+
# @return [String]
|
942
|
+
attr_reader :label
|
943
|
+
|
944
|
+
# @return [String]
|
945
|
+
attr_reader :kernel_params
|
946
|
+
|
947
|
+
def initialize(name:, label:, kernel_params:)
|
948
|
+
@name = name
|
949
|
+
@label = label
|
950
|
+
@kernel_params = kernel_params
|
951
|
+
end
|
952
|
+
|
953
|
+
def to_json(*args)
|
954
|
+
{
|
955
|
+
name:,
|
956
|
+
label:,
|
957
|
+
kernel_params:
|
958
|
+
}.to_json(*args)
|
959
|
+
end
|
801
960
|
end
|
802
961
|
|
803
962
|
NetbootBuilder.run
|
@@ -52,13 +52,15 @@ let
|
|
52
52
|
isoImages = cfg.isoImages;
|
53
53
|
};
|
54
54
|
|
55
|
-
builder = pkgs.
|
55
|
+
builder = pkgs.confReplaceVarsWith {
|
56
56
|
src = ./build-netboot-server.rb;
|
57
57
|
name = "build-netboot-server";
|
58
58
|
dir = "bin";
|
59
59
|
isExecutable = true;
|
60
|
-
|
61
|
-
|
60
|
+
replacements = {
|
61
|
+
ruby = pkgs.ruby;
|
62
|
+
jsonConfig = pkgs.writeText "netboot-server.json" builderConfig;
|
63
|
+
};
|
62
64
|
};
|
63
65
|
in {
|
64
66
|
options = {
|
@@ -0,0 +1,38 @@
|
|
1
|
+
{ config, lib, pkgs, confMachine, ... }:
|
2
|
+
let
|
3
|
+
inherit (lib) mkEnableOption mkIf;
|
4
|
+
|
5
|
+
cfg = config.confctl.programs.kexec-netboot;
|
6
|
+
|
7
|
+
kexecNetboot = pkgs.confReplaceVarsWith {
|
8
|
+
name = "kexec-netboot";
|
9
|
+
src = ./kexec-netboot.rb;
|
10
|
+
isExecutable = true;
|
11
|
+
replacements = {
|
12
|
+
ruby = pkgs.ruby;
|
13
|
+
kexecTools = pkgs.kexec-tools;
|
14
|
+
machineFqdn = confMachine.host.fqdn;
|
15
|
+
};
|
16
|
+
};
|
17
|
+
|
18
|
+
kexecNetbootBin = pkgs.runCommand "kexec-netboot-bin" {} ''
|
19
|
+
mkdir -p $out/bin
|
20
|
+
ln -s ${kexecNetboot} $out/bin/kexec-netboot
|
21
|
+
|
22
|
+
mkdir -p $out/share/man/man8
|
23
|
+
${pkgs.asciidoctor}/bin/asciidoctor \
|
24
|
+
-b manpage \
|
25
|
+
-D $out/share/man/man8 \
|
26
|
+
${./kexec-netboot.8.adoc}
|
27
|
+
'';
|
28
|
+
in {
|
29
|
+
options = {
|
30
|
+
confctl.programs.kexec-netboot = {
|
31
|
+
enable = mkEnableOption "Enable kexec-netboot utility";
|
32
|
+
};
|
33
|
+
};
|
34
|
+
|
35
|
+
config = mkIf cfg.enable {
|
36
|
+
environment.systemPackages = [ kexecNetbootBin ];
|
37
|
+
};
|
38
|
+
}
|
@@ -0,0 +1,62 @@
|
|
1
|
+
= kexec-netboot(8)
|
2
|
+
:doctype: manpage
|
3
|
+
:docdate: 2025-03-03
|
4
|
+
:manmanual: kexec-netboot
|
5
|
+
:mansource: kexec-netboot
|
6
|
+
:man-linkstyle: pass:[blue R < >]
|
7
|
+
|
8
|
+
== Name
|
9
|
+
|
10
|
+
kexec-netboot - Prepare machine for kexec using kernel/initrd from netboot server
|
11
|
+
|
12
|
+
== Synopsis
|
13
|
+
|
14
|
+
*kexec-netboot* [_options_]
|
15
|
+
|
16
|
+
== Description
|
17
|
+
|
18
|
+
*kexec-netboot* may be used to download kernel and initrd from the netboot server
|
19
|
+
the machine was booted from and load it using *kexec*.
|
20
|
+
|
21
|
+
It is possible to boot into any machine available on the netboot server
|
22
|
+
and to select generation and variant (default, single-user mode).
|
23
|
+
|
24
|
+
== Options
|
25
|
+
|
26
|
+
The following options are understood:
|
27
|
+
|
28
|
+
*-h*, *--help*::
|
29
|
+
Print a short help text and exit.
|
30
|
+
|
31
|
+
*-s*, *--server-url* _URL_::
|
32
|
+
Specify URL to the netboot server. By default, the URL is auto-detected
|
33
|
+
by reading *httproot* from */proc/cmdline*.
|
34
|
+
|
35
|
+
*-m*, *--machine* _FQDN_::
|
36
|
+
Select machine from the netboot server.
|
37
|
+
|
38
|
+
*-g*, *--generation* _GENERATION_::
|
39
|
+
Select machine generation identified by its number.
|
40
|
+
|
41
|
+
*-v*, *--variant* _VARIANT_::
|
42
|
+
Select generation variant identified by its name.
|
43
|
+
|
44
|
+
*-i*, *--interactive*::
|
45
|
+
Ask the user to select machine, generation and variant interactively.
|
46
|
+
|
47
|
+
*-a*, *--append* _PARAMS_::
|
48
|
+
Append parameters to the kernel command line.
|
49
|
+
|
50
|
+
*-u*, *--unload*::
|
51
|
+
Unload the current kexec target kernel and exit.
|
52
|
+
|
53
|
+
*-e*, *--exec*::
|
54
|
+
Run the currently loaded kernel.
|
55
|
+
|
56
|
+
== Bugs
|
57
|
+
|
58
|
+
Report bugs to https://github.com/vpsfreecz/confctl/issues.
|
59
|
+
|
60
|
+
== About
|
61
|
+
|
62
|
+
*kexec-netboot* is a part of https://github.com/vpsfreecz/confctl[confctl].
|