]> git.proxmox.com Git - pve-ha-manager.git/blob - src/PVE/HA/Tools.pm
fixing typos, also whitespace cleanup in PVE2 env class
[pve-ha-manager.git] / src / PVE / HA / Tools.pm
1 package PVE::HA::Tools;
2
3 use strict;
4 use warnings;
5 use JSON;
6 use PVE::JSONSchema;
7 use PVE::Tools;
8 use PVE::Cluster;
9
10 PVE::JSONSchema::register_format('pve-ha-resource-id', \&pve_verify_ha_resource_id);
11 sub 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
21 PVE::JSONSchema::register_standard_option('pve-ha-resource-id', {
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).",
23 typetext => "<type>:<name>",
24 type => 'string', format => 'pve-ha-resource-id',
25 });
26
27 PVE::JSONSchema::register_format('pve-ha-resource-or-vm-id', \&pve_verify_ha_resource_or_vm_id);
28 sub 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
38 PVE::JSONSchema::register_standard_option('pve-ha-resource-or-vm-id', {
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).",
40 typetext => "<type>:<name>",
41 type => 'string', format => 'pve-ha-resource-or-vm-id',
42 });
43
44 PVE::JSONSchema::register_format('pve-ha-group-node', \&pve_verify_ha_group_node);
45 sub 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
55 PVE::JSONSchema::register_standard_option('pve-ha-group-node-list', {
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').",
57 type => 'string', format => 'pve-ha-group-node-list',
58 typetext => '<node>[:<pri>]{,<node>[:<pri>]}*',
59 });
60
61 PVE::JSONSchema::register_standard_option('pve-ha-group-id', {
62 description => "The HA group identifier.",
63 type => 'string', format => 'pve-configid',
64 });
65
66 sub parse_sid {
67 my ($sid) = @_;
68
69 my ($type, $name);
70
71 if ($sid =~ m/^(\d+)$/) {
72 $name = $1;
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 }
88 } elsif ($sid =~m/^(\S+):(\S+)$/) {
89 $name = $2;
90 $type = $1;
91 } else {
92 die "unable to parse service id '$sid'\n";
93 }
94
95 return wantarray ? ($sid, $type, $name) : $sid;
96 }
97
98 sub 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
113 sub write_json_to_file {
114 my ($filename, $data) = @_;
115
116 my $raw = encode_json($data);
117
118 PVE::Tools::file_set_contents($filename, $raw);
119 }
120
121 sub 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 }
140
141 # bash auto completion helper
142
143 sub complete_sid {
144 my ($cmd, $pname, $cur) = @_;
145
146 my $cfg = PVE::HA::Config::read_resources_config();
147
148 my $res = [];
149
150 if ($cmd eq 'add') {
151
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;
175 }
176 }
177
178 return $res;
179 }
180
181 sub complete_enabled_sid {
182
183 my $cfg = PVE::HA::Config::read_resources_config();
184
185 my $res = [];
186 foreach my $sid (keys %{$cfg->{ids}}) {
187 my $state = $cfg->{ids}->{$sid}->{state} // 'enabled';
188 next if $state ne 'enabled';
189 push @$res, $sid;
190 }
191
192 return $res;
193 }
194
195 sub 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;
204 }
205
206 return $res;
207 }
208
209 sub 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
222 1;