X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=src%2FPVE%2FAPI2%2FHA%2FStatus.pm;h=6fd525bc299c89ab4693d20fdf71c05a69f5ab0a;hb=77bcb60a9d25784f7ee2c1eff4b57636c6891f89;hp=2a690d3a5bf12b29bab1ac7855433fe30a91473a;hpb=5c9d7bc9b4eb8c4fa83f4d19011a38e8e1420136;p=pve-ha-manager.git diff --git a/src/PVE/API2/HA/Status.pm b/src/PVE/API2/HA/Status.pm index 2a690d3..6fd525b 100644 --- a/src/PVE/API2/HA/Status.pm +++ b/src/PVE/API2/HA/Status.pm @@ -9,7 +9,6 @@ use PVE::Cluster; use PVE::HA::Config; use PVE::JSONSchema qw(get_standard_option); use PVE::RPCEnvironment; -use PVE::HA::Env::PVE2; use PVE::RESTHandler; @@ -31,8 +30,8 @@ my $timestamp_to_status = sub { }; __PACKAGE__->register_method ({ - name => 'index', - path => '', + name => 'index', + path => '', method => 'GET', permissions => { user => 'all' }, description => "Directory index.", @@ -50,7 +49,7 @@ __PACKAGE__->register_method ({ }, code => sub { my ($param) = @_; - + my $result = [ { name => 'current' }, { name => 'manager_status' }, @@ -60,10 +59,13 @@ __PACKAGE__->register_method ({ }}); __PACKAGE__->register_method ({ - name => 'status', + name => 'status', path => 'current', method => 'GET', description => "Get HA manger status.", + permissions => { + check => ['perm', '/', [ 'Sys.Audit' ]], + }, parameters => { additionalProperties => 0, properties => {}, @@ -73,59 +75,132 @@ __PACKAGE__->register_method ({ my ($param) = @_; my $res = []; - - if (PVE::Cluster::check_cfs_quorum(1)) { - push @$res, { id => 'quorum', type => 'quorum', + + my $quorate = PVE::Cluster::check_cfs_quorum(1); + if ($quorate) { + push @$res, { id => 'quorum', type => 'quorum', node => $nodename, status => "OK", quorate => 1 }; } else { - push @$res, { id => 'quorum', type => 'quorum', node => $nodename, + push @$res, { id => 'quorum', type => 'quorum', node => $nodename, status => "No quorum on node '$nodename'!", quorate => 0 }; } - - my $haenv = PVE::HA::Env::PVE2->new($nodename); - - my $status = $haenv->read_manager_status(); - my $ctime = $haenv->get_time(); + my $status = PVE::HA::Config::read_manager_status(); + + my $service_config = PVE::HA::Config::read_and_check_resources_config(); + + my $ctime = time(); if (defined($status->{master_node}) && defined($status->{timestamp})) { my $master = $status->{master_node}; my $status_str = &$timestamp_to_status($ctime, $status->{timestamp}); + # mark crm idle if it has no service configured and is not active + if ($quorate && $status_str ne 'active' && !keys %{$service_config}) { + $status_str = 'idle'; + } my $time_str = localtime($status->{timestamp}); my $status_text = "$master ($status_str, $time_str)"; - push @$res, { id => 'master', type => 'master', node => $master, + push @$res, { id => 'master', type => 'master', node => $master, status => $status_text, timestamp => $status->{timestamp} }; - } - + } + + # compute active services for all nodes + my $active_count = {}; + foreach my $sid (sort keys %{$status->{service_status}}) { + my $sd = $status->{service_status}->{$sid}; + next if !$sd->{node}; + $active_count->{$sd->{node}} = 0 if !defined($active_count->{$sd->{node}}); + my $req_state = $sd->{state}; + next if !defined($req_state); + next if $req_state eq 'stopped'; + next if $req_state eq 'freeze'; + $active_count->{$sd->{node}}++; + } + foreach my $node (sort keys %{$status->{node_status}}) { - my $lrm_status = $haenv->read_lrm_status($node); + my $lrm_status = PVE::HA::Config::read_lrm_status($node); my $id = "lrm:$node"; if (!$lrm_status->{timestamp}) { - push @$res, { id => $id, type => 'lrm', node => $node, - status => "$node (unable to read lrm status)"}; + push @$res, { id => $id, type => 'lrm', node => $node, + status => "$node (unable to read lrm status)"}; } else { my $status_str = &$timestamp_to_status($ctime, $lrm_status->{timestamp}); + my $lrm_mode = $lrm_status->{mode}; + + if ($status_str eq 'active') { + $lrm_mode ||= 'active'; + my $lrm_state = $lrm_status->{state} || 'unknown'; + if ($lrm_mode ne 'active') { + $status_str = "$lrm_mode mode"; + } else { + if ($lrm_state eq 'wait_for_agent_lock' && !$active_count->{$node}) { + $status_str = 'idle'; + } else { + $status_str = $lrm_state; + } + } + } elsif ($lrm_mode && $lrm_mode eq 'maintenance') { + $status_str = "$lrm_mode mode"; + } + my $time_str = localtime($lrm_status->{timestamp}); my $status_text = "$node ($status_str, $time_str)"; - push @$res, { id => $id, type => 'lrm', node => $node, - status => $status_text, timestamp => $lrm_status->{timestamp} }; + push @$res, { id => $id, type => 'lrm', node => $node, + status => $status_text, timestamp => $lrm_status->{timestamp} }; } } + my $add_service = sub { + my ($sid, $sc, $ss) = @_; + + my $data = { id => "service:$sid", type => 'service', sid => $sid }; + + if ($ss) { + $data->{node} = $ss->{node}; + $data->{crm_state} = $ss->{state}; + } elsif ($sc) { + $data->{node} = $sc->{node}; + } + my $node = $data->{node} // '---'; # to be save against manual tinkering + + $data->{state} = PVE::HA::Tools::get_verbose_service_state($ss, $sc); + $data->{status} = "$sid ($node, $data->{state})"; # backward compat. and CLI + + # also return common resource attributes + if (defined($sc)) { + $data->{request_state} = $sc->{state}; + foreach my $key (qw(group max_restart max_relocate comment)) { + $data->{$key} = $sc->{$key} if defined($sc->{$key}); + } + } + + push @$res, $data; + }; + foreach my $sid (sort keys %{$status->{service_status}}) { - my $d = $status->{service_status}->{$sid}; - push @$res, { id => "service:$sid", type => 'service', sid => $sid, - node => $d->{node}, status => "$sid ($d->{node}, $d->{state})" }; + my $sc = $service_config->{$sid}; + my $ss = $status->{service_status}->{$sid}; + $add_service->($sid, $sc, $ss); + } + + # show also service which aren't yet processed by the CRM + foreach my $sid (sort keys %$service_config) { + next if $status->{service_status}->{$sid}; + my $sc = $service_config->{$sid}; + $add_service->($sid, $sc); } - + return $res; }}); __PACKAGE__->register_method ({ - name => 'manager_status', + name => 'manager_status', path => 'manager_status', method => 'GET', description => "Get full HA manger status, including LRM status.", + permissions => { + check => ['perm', '/', [ 'Sys.Audit' ]], + }, parameters => { additionalProperties => 0, properties => {}, @@ -134,19 +209,17 @@ __PACKAGE__->register_method ({ code => sub { my ($param) = @_; - my $haenv = PVE::HA::Env::PVE2->new($nodename); + my $status = PVE::HA::Config::read_manager_status(); - my $status = $haenv->read_manager_status(); - my $data = { manager_status => $status }; $data->{quorum} = { node => $nodename, quorate => PVE::Cluster::check_cfs_quorum(1), }; - + foreach my $node (sort keys %{$status->{node_status}}) { - my $lrm_status = $haenv->read_lrm_status($node); + my $lrm_status = PVE::HA::Config::read_lrm_status($node); $data->{lrm_status}->{$node} = $lrm_status; }