]>
git.proxmox.com Git - pve-ha-manager.git/blob - src/PVE/HA/FenceConfig.pm
f8b5f19417976ec05a6ba159d1b94e8a779df866
1 package PVE
::HA
::FenceConfig
;
17 my $parse_errors = '';
19 my $parse_line = sub {
22 if ($line !~ m/^(device|connect)\s+(\S+)\s+(\S+)\s+(.+)$/) {
23 warn "$fn ignore line $lineno: $line\n";
26 my ($command, $dev_name, $target) = ($1, $2, $3);
27 my $arg_array = PVE
::Tools
::split_args
($4);
28 my $dev_number = 1; # default
30 # check for parallel devices
31 if ($dev_name =~ m/^(\w+)(:(\d+))?/) {
33 $dev_number = $3 if $3;
36 if ($command eq "device") {
37 my $dev = $config->{$dev_name} || {};
39 die "device '$dev_name:$dev_number' already declared\n"
40 if $dev && $dev->{sub_devs
}->{$dev_number};
42 $dev->{sub_devs
}->{$dev_number} = {
46 $dev->{priority
} = $priority++ if !$dev->{priority
};
48 $config->{$dev_name} = $dev;
50 } else { # connect nodes to devices
51 die "device '$dev_name' must be declared before you can connect to it\n"
52 if !$config->{$dev_name};
54 die "No parallel device '$dev_name:$dev_number' found\n"
55 if !$config->{$dev_name}->{sub_devs
}->{$dev_number};
57 my $sdev = $config->{$dev_name}->{sub_devs
}->{$dev_number};
59 my ($node) = $target =~ /node=(\w+)/;
60 die "node=nodename needed to connect device '$dev_name' to node\n"
63 die "node '$node' already connected to device '$dev_name:$dev_number'\n"
64 if $sdev->{node_args
}->{$node};
66 $sdev->{node_args
}->{$node} = $arg_array;
68 $config->{$dev_name}->{sub_devs
}->{$dev_number} = $sdev;
72 while ($raw =~ /^\h*(.*?)\h*$/gm) {
75 next if !$line || $line =~ /^#/;
77 eval { $parse_line->($line) };
79 $parse_errors .= "line $lineno: $err";
82 die "Encountered error(s) on parsing '$fn':\n$parse_errors" if $parse_errors;
92 my $prev_priority = -1;
94 foreach my $dev_name (sort {$data->{$a}->{priority
} <=> $data->{$b}->{priority
}} keys %$data) {
95 my $d = $data->{$dev_name};
97 die "Device '$dev_name' reuses priority! Priorities must be unique\n"
98 if $prev_priority == $d->{priority
};
100 $prev_priority = $d->{priority
};
102 foreach my $sub_dev_nr (sort keys %{$d->{sub_devs
}}) {
103 my $sub_dev = $d->{sub_devs
}->{$sub_dev_nr};
104 my $dev_arg_str = PVE
::Tools
::cmd2string
($sub_dev->{args
});
106 $raw .= "\ndevice $dev_name:$sub_dev_nr $sub_dev->{agent} $dev_arg_str\n";
108 foreach my $node (sort keys %{$sub_dev->{node_args
}}) {
109 my $node_arg_str = join (' ', @{$sub_dev->{node_args
}->{$node}});
111 $raw .= "connect $dev_name:$sub_dev_nr node=$node $node_arg_str\n";
122 my (@arguments) = @_;
125 foreach my $arg (@arguments) {
126 my ($key, $val) = split /=/, $arg;
127 # we need to differ long and short opts!
128 if (length($key) == 1) {
129 push @shell_args, "-${key}";
130 push @shell_args, PVE
::Tools
::shellquote
($val) if defined($val);
132 $key .= '='. PVE
::Tools
::shellquote
($val) if defined($val);
133 push @shell_args, "--$key";
137 return join (' ', @shell_args);
141 # returns command list to execute,
142 # can be more than one command if parallel devices are configured
143 # 'try' denotes the number of devices we should skip and normaly equals to
144 # failed fencing tries
146 my ($node, $try, $config) = @_;
148 return undef if !$node || !$config;
150 $try = 0 if !$try || $try<0;
152 foreach my $device (sort {$a->{priority
} <=> $b->{priority
}} values %$config) {
155 #foreach my $sub_dev (values %{$device->{sub_devs}}) {
156 foreach my $sub_dev_nr (sort keys %{$device->{sub_devs
}}) {
157 my $sub_dev = $device->{sub_devs
}->{$sub_dev_nr};
159 if (my $node_args = $sub_dev->{node_args
}->{$node}) {
160 push @commands, { agent
=>$sub_dev->{agent
},
161 sub_dev
=> $sub_dev_nr,
162 param
=> [@{$sub_dev->{args
}}, @{$node_args}]};
169 return [ @commands ] if $try<0;
173 # out of tries or no device for this node
179 my ($node, $config) = @_;
183 return 0 if !$config;
185 foreach my $device (values %$config) {
186 foreach my $sub_dev (values %{$device->{sub_devs
}}) {
187 if ($sub_dev->{node_args
}->{$node}) {
189 last; # no need to count parallel devices