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
|
package urpm::parallel_ka_run;
#- parallel resolve_dependencies
sub parallel_resolve_dependencies {
my ($parallel, $synthesis, $urpm, $state, $requested, %options) = @_;
#- first propagate the synthesis file to all machine.
$urpm->{log}("parallel_ka_run: mput $parallel->{options} -- '$synthesis' '$synthesis'");
system "mput $parallel->{options} -- '$synthesis' '$synthesis'";
$parallel->{synthesis} = $synthesis;
#- compute command line of urpm? tools.
my $line = $options{auto_select} ? ' --auto-select' : '';
foreach (keys %$requested) {
if (/\|/) {
#- simplified choices resolution.
my $choice = $options{callback_choices}->($urpm, undef, $state, [ map { /^\d+$/ ?
$urpm->{depslist}[$_] :
$urpm->search($_) } split '\|', $_ ]);
$line .= ' '.$choice->fullname;
} else {
my $pkg = $urpm->{depslist}[$_] or next;
$line .= ' '.$pkg->fullname;
}
}
#- execute urpmq to determine packages to install.
my ($node, $cont, %chosen);
local (*F, $_);
do {
$cont = 0; #- prepare to stop iteration.
#- the following state should be cleaned for each iteration.
delete $state->{selected};
#- now try an iteration of urpmq.
$urpm->{log}("parallel_ka_run: rshp -v $parallel->{options} -- urpmq --synthesis $synthesis -f $line ".join(' ', keys %chosen));
open F, "rshp -v $parallel->{options} -- urpmq --synthesis $synthesis -fdu $line ".join(' ', keys %chosen)." |";
while ($_ = <F>) {
chomp;
s/<([^>]*)>.*:->:(.*)/$2/ and $node = $1;
if (/\|/) {
#- distant urpmq returned a choices, check if it has already been chosen
#- or continue iteration to make sure no more choices are left.
$cont ||= 1; #- invalid transitory state (still choices is strange here if next sentence is not executed).
unless (grep { exists $chosen{$_} } split '\|', $_) {
#- it has not yet been chosen so need to ask user.
$cont = 2;
my $choice = $options{callback_choices}->($urpm, undef, $state, [ map { $urpm->search($_) } split '\|', $_ ]);
$chosen{scalar $choice->fullname} = $choice;
}
} else {
my $pkg = $urpm->search($_) or next; #TODO
$state->{selected}{$pkg->id}{$node} = $_;
}
}
close F or $urpm->{fatal}(1, _("rshp failed"));
#- check for internal error of resolution.
$cont == 1 and die "internal distant urpmq error on choice not taken";
} while ($cont);
#- keep trace of what has been chosen finally (if any).
$parallel->{line} = "$line ".join(' ', keys %chosen);
#- update ask_remove, ask_unselect too along with provided value.
#TODO
}
#- parallel install.
sub parallel_install {
my ($parallel, $urpm, $remove, $install, $upgrade) = @_;
foreach (values %$install, values %$upgrade) {
my ($basename) = /([^\/]*)$/;
$urpm->{log}("parallel_ka_run: mput $parallel->{options} -- '$_' $urpm->{cachedir}/rpms/$basename");
system "mput $parallel->{options} -- '$_' $urpm->{cachedir}/rpms/$basename";
}
local (*F, $_);
my ($node, %good_nodes, $bad);
$urpm->{log}("parallel_ka_run: rshp -v $parallel->{options} -- urpmi --no-locales --test --no-verify-rpm --auto --synthesis $parallel->{synthesis} $parallel->{line}");
open F, "rshp -v $parallel->{options} -- urpmi --no-locales --test --no-verify-rpm --auto --synthesis $parallel->{synthesis} $parallel->{line} |";
while ($_ = <F>) {
chomp;
s/<([^>]*)>.*:->:(.*)/$2/ and $node = $1;
/Installation is possible/ and $good_nodes{$node} = undef;
}
close F or $urpm->{fatal}(1, _("rshp failed"));
foreach (keys %{$parallel->{nodes}}) {
exists $good_nodes{$_} and next;
$urpm->{error}(_("Installation failed on node %s", $_) . ":\n" . ""); #TODO
$bad = 1;
}
unless ($bad) {
#- continue installation.
$urpm->{log}("parallel_ka_run: rshp $parallel->{options} -- urpmi --no-locales --no-verify-rpm --auto --synthesis $parallel->{synthesis} $parallel->{line}");
system "rshp $parallel->{options} -- urpmi --no-locales --no-verify-rpm --auto --synthesis $parallel->{synthesis} $parallel->{line}";
}
}
#- allow bootstrap from urpmi code directly (namespace is urpm).
package urpm;
sub handle_parallel_options {
my ($urpm, $options) = @_;
my ($ka_run_options) = $options =~ /ka-run:(.*)/;
if ($ka_run_options) {
my ($flush_nodes, %nodes);
foreach (split ' ', $ka_run_options) {
if ($_ eq '-m') {
$flush_nodes = 1;
} else {
$flush_nodes and $nodes{/host=([^,]*)/ ? $1 : $_} = undef;
undef $flush_nodes;
}
}
return bless {
options => $ka_run_options,
nodes => \%nodes,
}, "urpm::parallel_ka_run";
}
return undef;
}
1;
|