]> git.proxmox.com Git - pve-ha-manager.git/blob - src/PVE/CLI/ha_manager.pm
cli: expose new "crm-command node-maintenance enable/disable" commands
[pve-ha-manager.git] / src / PVE / CLI / ha_manager.pm
1 package PVE::CLI::ha_manager;
2
3 use strict;
4 use warnings;
5
6 use PVE::INotify;
7 use JSON;
8
9 use PVE::JSONSchema qw(get_standard_option);
10 use PVE::CLIHandler;
11 use PVE::Cluster;
12 use PVE::Tools qw(extract_param);
13 use PVE::RPCEnvironment;
14
15 use PVE::HA::Config; # needed for bash completion in PVE::HA::Tools!
16 use PVE::HA::Env::PVE2;
17 use PVE::HA::Tools;
18 use PVE::API2::HA::Resources;
19 use PVE::API2::HA::Groups;
20 use PVE::API2::HA::Status;
21
22 use base qw(PVE::CLIHandler);
23
24 my $nodename = PVE::INotify::nodename();
25
26 my $timestamp_to_status = sub {
27 my ($ctime, $timestamp) = @_;
28
29 my $tdiff = $ctime - $timestamp;
30 if ($tdiff > 30) {
31 return "old timestamp - dead?";
32 } elsif ($tdiff < -2) {
33 return "detected time drift!";
34 } else {
35 return "active";
36 }
37 };
38
39 sub setup_environment {
40 PVE::RPCEnvironment->setup_default_cli_env();
41 }
42
43 __PACKAGE__->register_method ({
44 name => 'status',
45 path => 'status',
46 method => 'GET',
47 description => "Display HA manger status.",
48 parameters => {
49 additionalProperties => 0,
50 properties => {
51 verbose => {
52 description => "Verbose output. Include complete CRM and LRM status (JSON).",
53 type => 'boolean',
54 default => 0,
55 optional => 1,
56 }
57 },
58 },
59 returns => { type => 'null' },
60 code => sub {
61 my ($param) = @_;
62
63 my $res = PVE::API2::HA::Status->status({});
64 foreach my $e (@$res) {
65 print "$e->{type} $e->{status}\n";
66 }
67
68 if ($param->{verbose}) {
69 print "full cluster state:\n";
70 my $data = PVE::API2::HA::Status->manager_status({});
71 print to_json($data, { pretty => 1, canonical => 1} );
72 }
73
74 return undef;
75 }});
76
77 __PACKAGE__->register_method ({
78 name => 'stop',
79 path => 'stop',
80 method => 'POST',
81 description => "Request the service to be stopped.",
82 permissions => {
83 check => ['perm', '/', [ 'Sys.Console' ]],
84 },
85 parameters => {
86 additionalProperties => 0,
87 properties => {
88 sid => get_standard_option('pve-ha-resource-or-vm-id', {
89 completion => \&PVE::HA::Tools::complete_sid
90 }),
91 timeout => {
92 description => "Timeout in seconds. If set to 0 a hard stop will be performed.",
93 type => 'integer',
94 minimum => 0,
95 },
96 },
97 },
98 returns => { type => 'null' },
99 code => sub {
100 my ($param) = @_;
101
102 my $sid = PVE::HA::Config::parse_sid(extract_param($param, 'sid'));
103
104 PVE::HA::Config::service_is_ha_managed($sid);
105
106 PVE::API2::HA::Resources::check_service_state($sid);
107
108 PVE::HA::Config::queue_crm_commands("stop $sid $param->{timeout}");
109
110 return undef;
111 }});
112
113 __PACKAGE__->register_method ({
114 name => 'node-maintenance-set',
115 path => 'node-maintenance-set',
116 method => 'POST',
117 description => "Change the node-maintenance request state.",
118 permissions => {
119 check => ['perm', '/', [ 'Sys.Console' ]],
120 },
121 parameters => {
122 additionalProperties => 0,
123 properties => {
124 node => get_standard_option('pve-node'),
125 disable => {
126 description => "Requests disabling or enabling maintenance-mode.",
127 type => 'boolean',
128 },
129 },
130 },
131 returns => { type => 'null' },
132 code => sub {
133 my ($param) = @_;
134
135 my $cmd = $param->{disable} ? 'disable-node-maintenance' : 'enable-node-maintenance';
136 PVE::HA::Config::queue_crm_commands("$cmd $param->{node}");
137
138 return undef;
139 }
140 });
141
142 our $cmddef = {
143 status => [ __PACKAGE__, 'status'],
144 config => [ 'PVE::API2::HA::Resources', 'index', [], {}, sub {
145 my $res = shift;
146 foreach my $rec (sort { $a->{sid} cmp $b->{sid} } @$res) {
147 my ($type, $name) = split(':', $rec->{sid}, 2);
148 print "$type:$name\n";
149 foreach my $k (sort keys %$rec) {
150 next if $k eq 'digest' || $k eq 'sid' ||
151 $k eq 'type' || $k eq 'errors';
152 print "\t$k $rec->{$k}\n";
153 }
154 if (my $errors = $rec->{errors}) {
155 foreach my $p (keys %$errors) {
156 warn "error: property '$p' - $errors->{$p}\n";
157 }
158 }
159 print "\n";
160 }}],
161 groupconfig => [ 'PVE::API2::HA::Groups', 'index', [], {}, sub {
162 my $res = shift;
163 foreach my $rec (sort { $a->{group} cmp $b->{group} } @$res) {
164 print "group: $rec->{group}\n";
165 foreach my $k (sort keys %$rec) {
166 next if $k eq 'digest' || $k eq 'group' ||
167 $k eq 'type';
168 print "\t$k $rec->{$k}\n";
169 }
170 print "\n";
171 }}],
172 groupadd => [ "PVE::API2::HA::Groups", 'create', ['group'] ],
173 groupremove => [ "PVE::API2::HA::Groups", 'delete', ['group'] ],
174 groupset => [ "PVE::API2::HA::Groups", 'update', ['group'] ],
175
176 add => [ "PVE::API2::HA::Resources", 'create', ['sid'] ],
177 remove => [ "PVE::API2::HA::Resources", 'delete', ['sid'] ],
178 set => [ "PVE::API2::HA::Resources", 'update', ['sid'] ],
179
180 migrate => { alias => 'crm-command migrate' },
181 relocate => { alias => 'crm-command relocate' },
182
183 'crm-command' => {
184 migrate => [ "PVE::API2::HA::Resources", 'migrate', ['sid', 'node'] ],
185 relocate => [ "PVE::API2::HA::Resources", 'relocate', ['sid', 'node'] ],
186 stop => [ __PACKAGE__, 'stop', ['sid', 'timeout'] ],
187 'node-maintenance' => {
188 enable => [ __PACKAGE__, 'node-maintenance-set', ['node'], { disable => 0 } ],
189 disable => [ __PACKAGE__, 'node-maintenance-set', ['node'], { disable => 1 } ],
190 },
191 }
192
193 };
194
195 1;