]>
git.proxmox.com Git - pve-ha-manager.git/blob - src/PVE/HA/FenceConfig.pm
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 } elsif ($command eq 'connect') { # 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;
69 # } elsif ($command eq 'fence_all') { # FIXME: TODO
71 die "command '$command' not implemented!";
75 while ($raw =~ /^\h*(.*?)\h*$/gm) {
78 next if !$line || $line =~ /^#/;
80 eval { $parse_line->($line) };
82 $parse_errors .= "line $lineno: $err";
85 die "Encountered error(s) on parsing '$fn':\n$parse_errors" if $parse_errors;
95 my $prev_priority = -1;
97 foreach my $dev_name (sort {$data->{$a}->{priority
} <=> $data->{$b}->{priority
}} keys %$data) {
98 my $d = $data->{$dev_name};
100 die "Device '$dev_name' reuses priority! Priorities must be unique\n"
101 if $prev_priority == $d->{priority
};
103 $prev_priority = $d->{priority
};
105 foreach my $sub_dev_nr (sort keys %{$d->{sub_devs
}}) {
106 my $sub_dev = $d->{sub_devs
}->{$sub_dev_nr};
107 my $dev_arg_str = PVE
::Tools
::cmd2string
($sub_dev->{args
});
109 $raw .= "\ndevice $dev_name:$sub_dev_nr $sub_dev->{agent} $dev_arg_str\n";
111 foreach my $node (sort keys %{$sub_dev->{node_args
}}) {
112 my $node_arg_str = join (' ', @{$sub_dev->{node_args
}->{$node}});
114 $raw .= "connect $dev_name:$sub_dev_nr node=$node $node_arg_str\n";
125 my (@arguments) = @_;
128 foreach my $arg (@arguments) {
129 my ($key, $val) = split /=/, $arg;
130 # we need to differ long and short opts!
131 if (length($key) == 1) {
132 push @shell_args, "-${key}";
133 push @shell_args, PVE
::Tools
::shellquote
($val) if defined($val);
135 $key .= '='. PVE
::Tools
::shellquote
($val) if defined($val);
136 push @shell_args, "--$key";
140 return join (' ', @shell_args);
144 # returns command list to execute,
145 # can be more than one command if parallel devices are configured
146 # 'try' denotes the number of devices we should skip and normaly equals to
147 # failed fencing tries
149 my ($node, $try, $config) = @_;
151 return undef if !$node || !$config;
153 $try = 0 if !$try || $try<0;
155 foreach my $device (sort {$a->{priority
} <=> $b->{priority
}} values %$config) {
158 #foreach my $sub_dev (values %{$device->{sub_devs}}) {
159 foreach my $sub_dev_nr (sort keys %{$device->{sub_devs
}}) {
160 my $sub_dev = $device->{sub_devs
}->{$sub_dev_nr};
162 if (my $node_args = $sub_dev->{node_args
}->{$node}) {
163 push @commands, { agent
=>$sub_dev->{agent
},
164 sub_dev
=> $sub_dev_nr,
165 param
=> [@{$sub_dev->{args
}}, @{$node_args}]};
172 return [ @commands ] if $try<0;
176 # out of tries or no device for this node
182 my ($node, $config) = @_;
186 return 0 if !$config;
188 foreach my $device (values %$config) {
189 foreach my $sub_dev (values %{$device->{sub_devs
}}) {
190 if ($sub_dev->{node_args
}->{$node}) {
192 last; # no need to count parallel devices multiple times