]>
git.proxmox.com Git - pve-ha-manager.git/blob - src/PVE/API2/HA/Resources.pm
1 package PVE
::API2
::HA
::Resources
;
7 use PVE
::Tools
qw(extract_param);
10 use PVE
::HA
::Resources
;
11 use HTTP
::Status
qw(:constants);
12 use Storable
qw(dclone);
13 use PVE
::JSONSchema
qw(get_standard_option);
14 use PVE
::RPCEnvironment
;
19 use base
qw(PVE::RESTHandler);
21 # fixme: use cfs_read_file
23 my $resource_type_enum = PVE
::HA
::Resources-
>lookup_types();
25 my $api_copy_config = sub {
28 die "no such resource '$sid'\n" if !$cfg->{ids
}->{$sid};
30 my $scfg = dclone
($cfg->{ids
}->{$sid});
32 $scfg->{digest
} = $cfg->{digest
};
37 sub check_service_state
{
38 my ($sid, $req_state) = @_;
40 my $service_status = PVE
::HA
::Config
::get_service_status
($sid);
41 if ($service_status->{managed
} && $service_status->{state} eq 'error') {
42 # service in error state, must get disabled before new state request
44 return if defined($req_state) && $req_state eq 'disabled';
45 die "service '$sid' in error state, must be disabled and fixed first\n";
49 __PACKAGE__-
>register_method ({
53 description
=> "List HA resources.",
55 check
=> ['perm', '/', [ 'Sys.Audit' ]],
58 additionalProperties
=> 0,
61 description
=> "Only list resources of specific type",
63 enum
=> $resource_type_enum,
72 properties
=> { sid
=> { type
=> 'string'} },
74 links
=> [ { rel
=> 'child', href
=> "{sid}" } ],
79 my $cfg = PVE
::HA
::Config
::read_resources_config
();
80 my $groups = PVE
::HA
::Config
::read_group_config
();
83 foreach my $sid (keys %{$cfg->{ids
}}) {
84 my $scfg = &$api_copy_config($cfg, $sid);
85 next if $param->{type
} && $param->{type
} ne $scfg->{type
};
86 if ($scfg->{group
} && !$groups->{ids
}->{$scfg->{group
}}) {
87 $scfg->{errors
}->{group
} = "group '$scfg->{group}' does not exist";
95 __PACKAGE__-
>register_method ({
100 check
=> ['perm', '/', [ 'Sys.Audit' ]],
102 description
=> "Read resource configuration.",
104 additionalProperties
=> 0,
106 sid
=> get_standard_option
('pve-ha-resource-or-vm-id',
107 { completion
=> \
&PVE
::HA
::Tools
::complete_sid
}),
114 my $cfg = PVE
::HA
::Config
::read_resources_config
();
116 my $sid = PVE
::HA
::Tools
::parse_sid
($param->{sid
});
118 return &$api_copy_config($cfg, $sid);
121 __PACKAGE__-
>register_method ({
127 check
=> ['perm', '/', [ 'Sys.Console' ]],
129 description
=> "Create a new HA resource.",
130 parameters
=> PVE
::HA
::Resources-
>createSchema(),
131 returns
=> { type
=> 'null' },
135 # create /etc/pve/ha directory
136 PVE
::Cluster
::check_cfs_quorum
();
137 mkdir("/etc/pve/ha");
139 my ($sid, $type, $name) = PVE
::HA
::Tools
::parse_sid
(extract_param
($param, 'sid'));
141 if (my $param_type = extract_param
($param, 'type')) {
142 # useless, but do it anyway
143 die "types does not match\n" if $param_type ne $type;
146 my $plugin = PVE
::HA
::Resources-
>lookup($type);
147 $plugin->verify_name($name);
149 $plugin->exists($name);
151 my $opts = $plugin->check_config($sid, $param, 1, 1);
153 PVE
::HA
::Config
::lock_ha_domain
(
156 my $cfg = PVE
::HA
::Config
::read_resources_config
();
158 if ($cfg->{ids
}->{$sid}) {
159 die "resource ID '$sid' already defined\n";
162 $cfg->{ids
}->{$sid} = $opts;
164 PVE
::HA
::Config
::write_resources_config
($cfg)
166 }, "create resource failed");
171 __PACKAGE__-
>register_method ({
176 description
=> "Update resource configuration.",
178 check
=> ['perm', '/', [ 'Sys.Console' ]],
180 parameters
=> PVE
::HA
::Resources-
>updateSchema(),
181 returns
=> { type
=> 'null' },
185 my $digest = extract_param
($param, 'digest');
186 my $delete = extract_param
($param, 'delete');
188 my ($sid, $type, $name) = PVE
::HA
::Tools
::parse_sid
(extract_param
($param, 'sid'));
190 if (my $param_type = extract_param
($param, 'type')) {
191 # useless, but do it anyway
192 die "types does not match\n" if $param_type ne $type;
195 if (my $group = $param->{group
}) {
196 my $group_cfg = PVE
::HA
::Config
::read_group_config
();
198 die "HA group '$group' does not exist\n"
199 if !$group_cfg->{ids
}->{$group};
202 check_service_state
($sid, $param->{state});
204 PVE
::HA
::Config
::lock_ha_domain
(
207 my $cfg = PVE
::HA
::Config
::read_resources_config
();
209 PVE
::SectionConfig
::assert_if_modified
($cfg, $digest);
211 my $scfg = $cfg->{ids
}->{$sid} ||
212 die "no such resource '$sid'\n";
214 my $plugin = PVE
::HA
::Resources-
>lookup($scfg->{type
});
215 my $opts = $plugin->check_config($sid, $param, 0, 1);
217 foreach my $k (%$opts) {
218 $scfg->{$k} = $opts->{$k};
222 my $options = $plugin->private()->{options
}->{$type};
223 foreach my $k (PVE
::Tools
::split_list
($delete)) {
224 my $d = $options->{$k} ||
225 die "no such option '$k'\n";
226 die "unable to delete required option '$k'\n"
228 die "unable to delete fixed option '$k'\n"
234 PVE
::HA
::Config
::write_resources_config
($cfg)
236 }, "update resource failed");
241 __PACKAGE__-
>register_method ({
246 description
=> "Delete resource configuration.",
248 check
=> ['perm', '/', [ 'Sys.Console' ]],
251 additionalProperties
=> 0,
253 sid
=> get_standard_option
('pve-ha-resource-or-vm-id',
254 { completion
=> \
&PVE
::HA
::Tools
::complete_sid
}),
257 returns
=> { type
=> 'null' },
261 my ($sid, $type, $name) = PVE
::HA
::Tools
::parse_sid
(extract_param
($param, 'sid'));
263 PVE
::HA
::Config
::service_is_ha_managed
($sid);
265 PVE
::HA
::Config
::lock_ha_domain
(
268 my $cfg = PVE
::HA
::Config
::read_resources_config
();
270 delete $cfg->{ids
}->{$sid};
272 PVE
::HA
::Config
::write_resources_config
($cfg)
274 }, "delete resource failed");
279 __PACKAGE__-
>register_method ({
282 path
=> '{sid}/migrate',
284 description
=> "Request resource migration (online) to another node.",
286 check
=> ['perm', '/', [ 'Sys.Console' ]],
289 additionalProperties
=> 0,
291 sid
=> get_standard_option
('pve-ha-resource-or-vm-id',
292 { completion
=> \
&PVE
::HA
::Tools
::complete_sid
}),
293 node
=> get_standard_option
('pve-node',
294 { completion
=> \
&PVE
::Cluster
::get_nodelist
}),
297 returns
=> { type
=> 'null' },
301 my ($sid, $type, $name) = PVE
::HA
::Tools
::parse_sid
(extract_param
($param, 'sid'));
303 PVE
::HA
::Config
::service_is_ha_managed
($sid);
305 check_service_state
($sid);
307 PVE
::HA
::Config
::queue_crm_commands
("migrate $sid $param->{node}");
312 __PACKAGE__-
>register_method ({
315 path
=> '{sid}/relocate',
317 description
=> "Request resource relocatzion to another node. This stops the service on the old node, and restarts it on the target node.",
319 check
=> ['perm', '/', [ 'Sys.Console' ]],
322 additionalProperties
=> 0,
324 sid
=> get_standard_option
('pve-ha-resource-or-vm-id',
325 { completion
=> \
&PVE
::HA
::Tools
::complete_sid
}),
326 node
=> get_standard_option
('pve-node',
327 { completion
=> \
&PVE
::Cluster
::get_nodelist
}),
330 returns
=> { type
=> 'null' },
334 my ($sid, $type, $name) = PVE
::HA
::Tools
::parse_sid
(extract_param
($param, 'sid'));
336 PVE
::HA
::Config
::service_is_ha_managed
($sid);
338 check_service_state
($sid);
340 PVE
::HA
::Config
::queue_crm_commands
("relocate $sid $param->{node}");