]> git.proxmox.com Git - pve-ha-manager.git/blame - src/PVE/HA/Tools.pm
vm_is_ha_managed: allow check on service state
[pve-ha-manager.git] / src / PVE / HA / Tools.pm
CommitLineData
54fc75de
DM
1package PVE::HA::Tools;
2
3use strict;
4use warnings;
a223f4cc
DM
5use JSON;
6use PVE::JSONSchema;
54fc75de 7use PVE::Tools;
427e33b6 8use PVE::Cluster;
54fc75de 9
95ea5d67
DM
10PVE::JSONSchema::register_format('pve-ha-resource-id', \&pve_verify_ha_resource_id);
11sub pve_verify_ha_resource_id {
12 my ($sid, $noerr) = @_;
13
14 if ($sid !~ m/^[a-z]+:\S+$/) {
15 return undef if $noerr;
16 die "value does not look like a valid ha resource id\n";
17 }
18 return $sid;
19}
20
21PVE::JSONSchema::register_standard_option('pve-ha-resource-id', {
427e33b6 22 description => "HA resource ID. This consists of a resource type followed by a resource specific name, separated with colon (example: vm:100 / ct:100).",
95ea5d67
DM
23 typetext => "<type>:<name>",
24 type => 'string', format => 'pve-ha-resource-id',
25});
26
6ca2edcd
DM
27PVE::JSONSchema::register_format('pve-ha-resource-or-vm-id', \&pve_verify_ha_resource_or_vm_id);
28sub pve_verify_ha_resource_or_vm_id {
29 my ($sid, $noerr) = @_;
30
31 if ($sid !~ m/^([a-z]+:\S+|\d+)$/) {
32 return undef if $noerr;
33 die "value does not look like a valid ha resource id\n";
34 }
35 return $sid;
36}
37
38PVE::JSONSchema::register_standard_option('pve-ha-resource-or-vm-id', {
427e33b6 39 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).",
6ca2edcd
DM
40 typetext => "<type>:<name>",
41 type => 'string', format => 'pve-ha-resource-or-vm-id',
42});
43
a223f4cc
DM
44PVE::JSONSchema::register_format('pve-ha-group-node', \&pve_verify_ha_group_node);
45sub pve_verify_ha_group_node {
46 my ($node, $noerr) = @_;
47
48 if ($node !~ m/^([a-zA-Z0-9]([a-zA-Z0-9\-]*[a-zA-Z0-9])?)(:\d+)?$/) {
49 return undef if $noerr;
50 die "value does not look like a valid ha group node\n";
51 }
52 return $node;
53}
54
55PVE::JSONSchema::register_standard_option('pve-ha-group-node-list', {
63f6a08c 56 description => "List of cluster node names with optional priority. We use priority '0' as default. The CRM tries to run services on the node with highest priority (also see option 'nofailback').",
a223f4cc
DM
57 type => 'string', format => 'pve-ha-group-node-list',
58 typetext => '<node>[:<pri>]{,<node>[:<pri>]}*',
59});
60
61PVE::JSONSchema::register_standard_option('pve-ha-group-id', {
62 description => "The HA group identifier.",
63 type => 'string', format => 'pve-configid',
64});
65
b47a7a1b
DM
66sub parse_sid {
67 my ($sid) = @_;
68
6ca2edcd
DM
69 my ($type, $name);
70
71 if ($sid =~ m/^(\d+)$/) {
72 $name = $1;
427e33b6
AG
73 my $vmlist = PVE::Cluster::get_vmlist();
74 if (defined($vmlist->{ids}->{$name})) {
75 my $vm_type = $vmlist->{ids}->{$name}->{type};
76 if ($vm_type eq 'lxc') {
77 $type = 'ct';
78 } elsif ($vm_type eq 'qemu') {
79 $type = 'vm';
80 } else {
81 die "internal error";
82 }
83 $sid = "$type:$name";
84 }
85 else {
86 die "unable do add resource - VM/CT $1 does not exist\n";
87 }
6ca2edcd
DM
88 } elsif ($sid =~m/^(\S+):(\S+)$/) {
89 $name = $2;
90 $type = $1;
91 } else {
92 die "unable to parse service id '$sid'\n";
93 }
b47a7a1b 94
6ca2edcd 95 return wantarray ? ($sid, $type, $name) : $sid;
b47a7a1b
DM
96}
97
54fc75de
DM
98sub read_json_from_file {
99 my ($filename, $default) = @_;
100
101 my $data;
102
103 if (defined($default) && (! -f $filename)) {
104 $data = $default;
105 } else {
106 my $raw = PVE::Tools::file_get_contents($filename);
107 $data = decode_json($raw);
108 }
109
110 return $data;
111}
112
113sub write_json_to_file {
114 my ($filename, $data) = @_;
115
116 my $raw = encode_json($data);
a223f4cc 117
54fc75de
DM
118 PVE::Tools::file_set_contents($filename, $raw);
119}
120
49777d09
DM
121sub count_fenced_services {
122 my ($ss, $node) = @_;
123
124 my $count = 0;
125
126 foreach my $sid (keys %$ss) {
127 my $sd = $ss->{$sid};
128 next if !$sd->{node};
129 next if $sd->{node} ne $node;
130 my $req_state = $sd->{state};
131 next if !defined($req_state);
132 if ($req_state eq 'fence') {
133 $count++;
134 next;
135 }
136 }
137
138 return $count;
139}
54fc75de 140
cdf272a0
TL
141# bash auto completion helper
142
143sub complete_sid {
bf119a50 144 my ($cmd, $pname, $cur) = @_;
cdf272a0 145
bf119a50 146 my $cfg = PVE::HA::Config::read_resources_config();
cdf272a0
TL
147
148 my $res = [];
cdf272a0 149
bf119a50 150 if ($cmd eq 'add') {
cdf272a0 151
bf119a50
DM
152 my $vmlist = PVE::Cluster::get_vmlist();
153
154 while (my ($vmid, $info) = each %{$vmlist->{ids}}) {
155
156 my $sid;
157
158 if ($info->{type} eq 'lxc') {
159 $sid = "ct:$vmid";
160 } elsif ($info->{type} eq 'qemu') {
161 $sid = "vm:$vmid";
162 } else {
163 next; # should not happen
164 }
165
166 next if $cfg->{ids}->{$sid};
167
168 push @$res, $sid;
169 }
170
171 } else {
172
173 foreach my $sid (keys %{$cfg->{ids}}) {
174 push @$res, $sid;
cdf272a0 175 }
bf119a50 176 }
cdf272a0 177
bf119a50
DM
178 return $res;
179}
180
181sub complete_enabled_sid {
182
183 my $cfg = PVE::HA::Config::read_resources_config();
cdf272a0 184
bf119a50
DM
185 my $res = [];
186 foreach my $sid (keys %{$cfg->{ids}}) {
187 my $state = $cfg->{ids}->{$sid}->{state} // 'enabled';
188 next if $state ne 'enabled';
cdf272a0 189 push @$res, $sid;
bf119a50 190 }
cdf272a0 191
bf119a50
DM
192 return $res;
193}
194
195sub complete_disabled_sid {
196
197 my $cfg = PVE::HA::Config::read_resources_config();
198
199 my $res = [];
200 foreach my $sid (keys %{$cfg->{ids}}) {
201 my $state = $cfg->{ids}->{$sid}->{state} // 'enabled';
202 next if $state eq 'enabled';
203 push @$res, $sid;
cdf272a0
TL
204 }
205
206 return $res;
207}
208
209sub complete_group {
210
211 my $cfg = PVE::HA::Config::read_group_config();
212
213 my $res = [];
214 foreach my $group (keys %{$cfg->{ids}}) {
215 push @$res, $group;
216 }
217
218 return $res;
219}
220
221
54fc75de 2221;