]> git.proxmox.com Git - pve-ha-manager.git/blobdiff - src/PVE/HA/Tools.pm
fix #1919, #1920: improve handling zombie (without node) services
[pve-ha-manager.git] / src / PVE / HA / Tools.pm
index dca7dafb31c73a40e6e06cd7ca3008d71eb1116a..81785efbd3f5d9c6086d26d09e4f89bf098ab5c6 100644 (file)
@@ -3,9 +3,9 @@ package PVE::HA::Tools;
 use strict;
 use warnings;
 use JSON;
+
 use PVE::JSONSchema;
 use PVE::Tools;
-use PVE::Cluster;
 use PVE::ProcFSTools;
 
 # return codes used in the ha environment
@@ -41,7 +41,7 @@ sub pve_verify_ha_resource_id {
 PVE::JSONSchema::register_standard_option('pve-ha-resource-id', {
     description => "HA resource ID. This consists of a resource type followed by a resource specific name, separated with colon (example: vm:100 / ct:100).",
     typetext => "<type>:<name>",
-    type => 'string', format => 'pve-ha-resource-id',                                   
+    type => 'string', format => 'pve-ha-resource-id',
 });
 
 PVE::JSONSchema::register_format('pve-ha-resource-or-vm-id', \&pve_verify_ha_resource_or_vm_id);
@@ -58,7 +58,7 @@ sub pve_verify_ha_resource_or_vm_id {
 PVE::JSONSchema::register_standard_option('pve-ha-resource-or-vm-id', {
     description => "HA resource ID. This consists of a resource type followed by a resource specific name, separated with colon (example: vm:100 / ct:100). For virtual machines and containers, you can simply use the VM or CT id as a shortcut (example: 100).",
     typetext => "<type>:<name>",
-    type => 'string', format => 'pve-ha-resource-or-vm-id',                                     
+    type => 'string', format => 'pve-ha-resource-or-vm-id',
 });
 
 PVE::JSONSchema::register_format('pve-ha-group-node', \&pve_verify_ha_group_node);
@@ -84,38 +84,6 @@ PVE::JSONSchema::register_standard_option('pve-ha-group-id', {
     type => 'string', format => 'pve-configid',
 });
 
-sub parse_sid {
-    my ($sid) = @_;
-
-    my ($type, $name);
-
-    if ($sid =~ m/^(\d+)$/) {
-       $name = $1;
-       my $vmlist = PVE::Cluster::get_vmlist();
-       if (defined($vmlist->{ids}->{$name})) {
-           my $vm_type = $vmlist->{ids}->{$name}->{type};
-           if ($vm_type eq 'lxc') {
-               $type = 'ct';
-           } elsif ($vm_type eq 'qemu') {
-               $type = 'vm';
-           } else {
-               die "internal error";
-           }
-           $sid = "$type:$name";
-       }
-       else {
-           die "unable do add resource - VM/CT $1 does not exist\n";
-       }
-    } elsif  ($sid =~m/^(\S+):(\S+)$/) {
-       $name = $2;
-       $type = $1;
-    } else {
-       die "unable to parse service id '$sid'\n";
-    }
-
-    return wantarray ? ($sid, $type, $name) : $sid;
-}
-
 sub read_json_from_file {
     my ($filename, $default) = @_;
 
@@ -124,16 +92,7 @@ sub read_json_from_file {
     if (defined($default) && (! -f $filename)) {
        $data = $default;
     } else {
-       my $raw;
-       # workaround for bug #775
-       if ($filename =~ m|^/etc/pve/|) {
-           $filename =~ s|^/etc/pve/+||;
-           $raw = PVE::Cluster::get_config($filename);
-           die "unable to read file '/etc/pve/$filename'\n" 
-               if !defined($raw);
-       } else {
-           $raw = PVE::Tools::file_get_contents($filename);
-       }
+       my $raw = PVE::Tools::file_get_contents($filename);
        $data = decode_json($raw);
     }
 
@@ -148,26 +107,11 @@ sub write_json_to_file {
     PVE::Tools::file_set_contents($filename, $raw);
 }
 
-sub has_services {
-    my ($haenv, $node) = @_;
-
-    my $conf = $haenv->read_service_config();
-
-    # if no node defined any service count is fine
-    return scalar(%{$conf}) if !defined($node);
-
-    foreach my $d (values %$conf) {
-       return 1 if $d->{node} eq $node;
-    }
-
-    return undef;
-}
-
 sub count_fenced_services {
     my ($ss, $node) = @_;
 
     my $count = 0;
-    
+
     foreach my $sid (keys %$ss) {
        my $sd = $ss->{$sid};
        next if !$sd->{node};
@@ -179,10 +123,46 @@ sub count_fenced_services {
            next;
        }
     }
-    
+
     return $count;
 }
 
+sub get_verbose_service_state {
+    my ($service_state, $service_conf) = @_;
+
+    my $req = $service_conf->{state} // 'ignored';
+    return 'ignored' if $req eq 'ignored';
+
+    return 'not found' if !defined($service_conf->{node});
+
+    # service not yet processed by manager
+    return 'queued' if !defined($service_state);
+    my $cur = $service_state->{state};
+
+    # give fast feedback to the user
+    my $state = $cur;
+    if (!defined($cur)) {
+       $state = 'queued';
+    } elsif ($cur eq 'stopped') {
+       if ($req eq 'started') {
+           $state = 'starting';
+       } elsif ($req eq 'disabled') {
+           $state = 'disabled';
+       }
+    } elsif ($cur eq 'started') {
+       if ($req eq 'stopped' || $req eq 'disabled') {
+           $state = 'stopping';
+       }
+       $state = 'starting' if !$service_state->{running};
+    } elsif ($cur eq 'error') {
+       if ($req eq 'disabled') {
+           $state = 'clearing error flag';
+       }
+    }
+
+    return $state;
+}
+
 sub upid_wait {
     my ($upid, $haenv) = @_;
 
@@ -196,6 +176,11 @@ sub upid_wait {
 
 # bash auto completion helper
 
+# NOTE: we use PVE::HA::Config here without declaring an 'use' clause above as
+# an hack. It uses the PVE::Cluster module from pve-cluster, which we do not
+# have nor want as dependency in the simulator - where the completion helpers
+# are never called. The PVE::CLI::ha_manager package pulls it in for us.
+
 sub complete_sid {
     my ($cmd, $pname, $cur) = @_;
 
@@ -235,7 +220,6 @@ sub complete_sid {
 }
 
 sub complete_enabled_sid {
-
     my $cfg = PVE::HA::Config::read_resources_config();
 
     my $res = [];
@@ -249,7 +233,6 @@ sub complete_enabled_sid {
 }
 
 sub complete_disabled_sid {
-
     my $cfg = PVE::HA::Config::read_resources_config();
 
     my $res = [];
@@ -279,5 +262,4 @@ sub complete_group {
     return $res;
 }
 
-
 1;