forked from openSUSE/perl-bootloader
-
Notifications
You must be signed in to change notification settings - Fork 0
/
pbl-yaml
executable file
·225 lines (171 loc) · 5.26 KB
/
pbl-yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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
75
76
77
78
79
80
81
82
83
84
85
86
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
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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
#! /usr/bin/perl
use strict;
use Getopt::Long;
use Data::Dumper;
# There are various YAML implementations for perl. These are the main
# options:
#
# YAML: has problems parsing its own data
# YAML::Tiny: has huge problems parsing its own data
# YAML::Syck: works, doesn't make a difference between '1' and 1
# YAML::XS: works, makes strings utf8 when reading data
use YAML::XS;
use Bootloader::Tools;
# Explicitly load all loader specific modules as Bootloader::Library
# normally loads them depending on loader type but we don't know in advance
# what objects show up in our YAML input data.
#
eval "use Bootloader::Core::$_" for qw ( ELILO GRUB GRUB2 GRUB2EFI LILO NONE PowerLILO ZIPL );
sub Usage;
sub ReadYAML;
sub WriteYAML;
# we need something to log to until we have the real state setup
my $logger = Bootloader::Library->new();
# the current state
my $pbl_state;
my $opt_state_in;
my $opt_state_out;
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# parse arguments
Usage 0 if @ARGV == 0;
GetOptions(
'state-in=s' => \$opt_state_in,
'state-out=s' => \$opt_state_out,
'state=s' => sub { $opt_state_out = $opt_state_in = $_[1] },
'version' => sub { print "$Bootloader::Library::VERSION\n"; exit 0 },
'help' => sub { Usage 0 },
) || Usage 1;
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# read existing state, if any
if($opt_state_in) {
$pbl_state = ReadYAML($opt_state_in, 1);
if($pbl_state) {
# increment session id
$pbl_state->{session_id} =~ s/\.(\d+)$/.${\($1+1)}/;
# restart log
$pbl_state->StartLog();
}
}
# if we didn't get a saved state, start with a fresh one
$pbl_state = $logger if !defined $pbl_state;
# use normal logging function
$logger = $pbl_state;
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# process all commands
# command format: 'foo=Func(bar)' (no spaces!)
# foo and bar are optional
for my $cmd (@ARGV) {
if($cmd =~ /^(([^=]+)=)?([\w]+)\(([^()]*)\)$/) {
my $res_file = $2;
my $func = $3;
my $arg_file = $4;
my $multi = $arg_file =~ s/^@//;
my @args;
if($arg_file ne "") {
my $args = ReadYAML($arg_file);
if($multi && ref($args) eq 'ARRAY') {
@args = @$args;
}
else {
@args = ($args);
}
}
my $res;
if(exists $Bootloader::Tools::{$func}) {
# InitLibrary() is a bit special, as it creates the state
if($func eq 'InitLibrary') {
$res = Bootloader::Tools::InitLibrary($pbl_state);
}
else {
Bootloader::Tools::SetState($pbl_state);
eval "\$res = Bootloader::Tools::$func(\@args)";
}
}
elsif(exists $Bootloader::Library::{$func}) {
$res = $pbl_state->$func(@args);
}
else {
$logger->error("$func: no such function");
}
WriteYAML($res_file, $res) if $res_file ne "";
}
else {
$logger->error("$cmd: invalid command format");
}
}
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# store final state
WriteYAML($opt_state_out, $pbl_state) if $opt_state_out;
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
sub Usage
{
my $err = $_[0];
if($err) {
print STDERR "Try 'pbl-yaml --help' for more information.\n";
exit $err;
}
print <<" usage";
Usage: pbl-yaml [OPTIONS] COMMANDS
perl-Bootloader library call wrapper using YAML files for arguments.
Options:
--state-in FILE Read perl-Bootloader state from FILE.
If it can't be read, a new state is created.
--state-out FILE Store final perl-Bootloader state in FILE.
--state FILE Use FILE for reading and storing the state.
--version Print perl-Bootloader version.
--help Write this help text.
Commands:
COMMANDS have the form 'RESULT=FUNCTION(ARGUMENT) or RESULT=FUNCTION(\@ARGUMENTS)'.
ARGUMENT is a YAML file containing a single argument. ARGUMENTS is a YAML
file containing an array of arguments. The return value of FUNCTION will
be stored in RESULT. RESULT and ARGUMENT are optional.
FUNCTION is a function from either Bootloader::Tools or Bootloader::Library.
Examples:
pbl-yaml --state foo1 'InitLibrary()' 'bar=ReadSettings()'
pbl-yaml --state foo2 'x1=GetDeviceMapping()' 'x2=ReadMountPoints(x1)' 'x3=ReadPartitions(x1)'
Note:
Logging is done via perl-Bootloader. That means it ends up in
/var/log/pbl.log or on STDERR if that file is not writable.
usage
exit $err;
}
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Read data from file.
#
sub ReadYAML
{
my $file = $_[0];
my $warn_only = $_[1];
my $x;
if(open my $f, "<", $file) {
local $/;
$_ = <$f>;
close $f;
$x = YAML::XS::Load($_);
}
if(!defined $x) {
if($warn_only) {
$logger->milestone("$file: no YAML data");
}
else {
$logger->error("$file: no YAML data");
}
}
return $x;
}
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Write data to file.
#
sub WriteYAML
{
my $file = $_[0];
my $data = $_[1];
my $x = YAML::XS::Dump($data);
if(defined $x && open my $f, ">", $file) {
print $f $x;
close $f;
}
else {
$logger->error("$file: failed to write YAML data");
}
}