Fix pvecm status parsing for QDevice flags (#738)

This commit is contained in:
courtmanr@gmail.com 2025-11-22 23:44:01 +00:00
parent d5fdf2f471
commit b2c4a583f7
4 changed files with 98 additions and 13 deletions

View file

@ -732,12 +732,13 @@ func discoverClusterNodes() ([]string, error) {
}
// Parse output to extract IP addresses
// Format example:
// 0x00000001 1 192.168.0.134
// 0x00000003 1 192.168.0.5 (local)
return parseClusterNodes(out.String())
}
// parseClusterNodes parses pvecm status output to extract IP addresses
func parseClusterNodes(output string) ([]string, error) {
var nodes []string
lines := strings.Split(out.String(), "\n")
lines := strings.Split(output, "\n")
for _, line := range lines {
// Look for lines with hex ID and IP address
if !strings.Contains(line, "0x") {
@ -750,11 +751,18 @@ func discoverClusterNodes() ([]string, error) {
continue
}
// Third field should be the IP address
ip := fields[2]
// Basic validation that it looks like an IP
if strings.Contains(ip, ".") {
nodes = append(nodes, ip)
// Iterate through fields to find the IP address
for _, field := range fields {
// Skip hex ID
if strings.HasPrefix(field, "0x") {
continue
}
// Check if it's a valid IP
if ip := net.ParseIP(field); ip != nil {
nodes = append(nodes, field)
break
}
}
}

View file

@ -0,0 +1,77 @@
package main
import (
"testing"
)
func TestParseClusterNodes(t *testing.T) {
tests := []struct {
name string
output string
want []string
wantErr bool
}{
{
name: "standard output",
output: `Membership information
----------------------
Nodeid Votes Name
0x00000001 1 192.168.1.10
0x00000002 1 192.168.1.11`,
want: []string{"192.168.1.10", "192.168.1.11"},
},
{
name: "output with QDevice flags",
output: `Membership information
----------------------
Nodeid Votes Name
0x00000001 1 A,V,NMW 192.168.1.10
0x00000002 1 A,V,NMW 192.168.1.11`,
want: []string{"192.168.1.10", "192.168.1.11"},
},
{
name: "output with local suffix",
output: `Membership information
----------------------
Nodeid Votes Name
0x00000001 1 192.168.1.10 (local)
0x00000002 1 192.168.1.11`,
want: []string{"192.168.1.10", "192.168.1.11"},
},
{
name: "mixed output",
output: `Membership information
----------------------
Nodeid Votes Name
0x00000001 1 A,V,NMW 192.168.1.10 (local)
0x00000002 1 192.168.1.11`,
want: []string{"192.168.1.10", "192.168.1.11"},
},
{
name: "no nodes",
output: "some random text",
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := parseClusterNodes(tt.output)
if (err != nil) != tt.wantErr {
t.Errorf("parseClusterNodes() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !tt.wantErr {
if len(got) != len(tt.want) {
t.Errorf("parseClusterNodes() got = %v, want %v", got, tt.want)
} else {
for i := range got {
if got[i] != tt.want[i] {
t.Errorf("parseClusterNodes() got[%d] = %v, want %v", i, got[i], tt.want[i])
}
}
}
}
})
}
}

View file

@ -805,7 +805,7 @@ cleanup_cluster_authorized_keys_manual() {
if command -v pvecm >/dev/null 2>&1; then
while IFS= read -r node_ip; do
[[ -n "$node_ip" ]] && nodes+=("$node_ip")
done < <(pvecm status 2>/dev/null | awk '/0x[0-9a-f]+.*[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/ {print $3}' || true)
done < <(pvecm status 2>/dev/null | awk '/0x[0-9a-f]+.*[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/ {for(i=1;i<=NF;i++) if($i ~ /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/) print $i}' || true)
fi
if [[ ${#nodes[@]} -eq 0 ]]; then
@ -2646,7 +2646,7 @@ if [[ -z "$HOST" ]]; then
# Discover cluster nodes
if command -v pvecm >/dev/null 2>&1; then
CLUSTER_NODES=$(pvecm status 2>/dev/null | awk '/0x[0-9a-f]+.*[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/ {print $3}' || true)
CLUSTER_NODES=$(pvecm status 2>/dev/null | awk '/0x[0-9a-f]+.*[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/ {for(i=1;i<=NF;i++) if($i ~ /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/) print $i}' || true)
if [[ -n "$CLUSTER_NODES" ]]; then
for node_ip in $CLUSTER_NODES; do
@ -2955,7 +2955,7 @@ print_info "Proxy public key: ${PROXY_PUBLIC_KEY:0:50}..."
# Discover cluster nodes
if command -v pvecm >/dev/null 2>&1; then
# Extract node IPs from pvecm status
CLUSTER_NODES=$(pvecm status 2>/dev/null | awk '/0x[0-9a-f]+.*[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/ {print $3}' || true)
CLUSTER_NODES=$(pvecm status 2>/dev/null | awk '/0x[0-9a-f]+.*[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/ {for(i=1;i<=NF;i++) if($i ~ /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/) print $i}' || true)
if [[ -n "$CLUSTER_NODES" ]]; then
print_info "Discovered cluster nodes: $(echo $CLUSTER_NODES | tr '\n' ' ')"

View file

@ -50,7 +50,7 @@ if [[ -z "$HOST" ]]; then
# Discover cluster nodes
if command -v pvecm >/dev/null 2>&1; then
CLUSTER_NODES=$(pvecm status 2>/dev/null | awk '/0x[0-9a-f]+.*[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/ {print $3}')
CLUSTER_NODES=$(pvecm status 2>/dev/null | awk '/0x[0-9a-f]+.*[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/ {for(i=1;i<=NF;i++) if($i ~ /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/) print $i}')
if [[ -n "$CLUSTER_NODES" ]]; then
for node_ip in $CLUSTER_NODES; do