]>
git.proxmox.com Git - pve-manager-legacy.git/blob - PVE/CLI/pvenode.pm
1 package PVE
::CLI
::pvenode
;
7 use PVE
::API2
::ACMEAccount
;
8 use PVE
::API2
::ACMEPlugin
;
9 use PVE
::API2
::Certificates
;
10 use PVE
::API2
::NodeConfig
;
14 use PVE
::ACME
::Challenge
;
17 use PVE
::Exception
qw(raise_param_exc raise);
18 use PVE
::JSONSchema
qw(get_standard_option);
20 use PVE
::RPCEnvironment
;
21 use PVE
::CLIFormatter
;
27 use base
qw(PVE::CLIHandler);
29 my $nodename = PVE
::INotify
::nodename
();
31 sub setup_environment
{
32 PVE
::RPCEnvironment-
>setup_default_cli_env();
37 my $status = PVE
::Tools
::upid_read_status
($upid);
38 print "Task $status\n";
39 exit(PVE
::Tools
::upid_status_is_error
($status) ?
-1 : 0);
45 my $load_file_and_encode = sub {
48 return PVE
::ACME
::Challenge-
>encode_value('string', 'data', PVE
::Tools
::file_get_contents
($filename));
52 'upload_custom_cert' => [
57 ['data', $load_file_and_encode, "File with one key-value pair per line, will be base64url encode for storage in plugin config.", 0],
60 ['data', $load_file_and_encode, "File with one key-value pair per line, will be base64url encode for storage in plugin config.", 0],
64 return $mapping->{$name};
67 __PACKAGE__-
>register_method({
68 name
=> 'acme_register',
69 path
=> 'acme_register',
71 description
=> "Register a new ACME account with a compatible CA.",
73 additionalProperties
=> 0,
75 name
=> get_standard_option
('pve-acme-account-name'),
76 contact
=> get_standard_option
('pve-acme-account-contact'),
77 directory
=> get_standard_option
('pve-acme-directory-url', {
82 returns
=> { type
=> 'null' },
86 if (!$param->{directory
}) {
87 my $directories = PVE
::API2
::ACMEAccount-
>get_directories({});
88 print "Directory endpoints:\n";
90 while ($i < @$directories) {
91 print $i, ") ", $directories->[$i]->{name
}, " (", $directories->[$i]->{url
}, ")\n";
94 print $i, ") Custom\n";
96 my $term = Term
::ReadLine-
>new('pvenode');
97 my $get_dir_selection = sub {
98 my $selection = $term->readline("Enter selection: ");
99 if ($selection =~ /^(\d+)$/) {
101 if ($selection == $i) {
102 $param->{directory
} = $term->readline("Enter custom URL: ");
104 } elsif ($selection < $i && $selection >= 0) {
105 $param->{directory
} = $directories->[$selection]->{url
};
109 print "Invalid selection.\n";
113 while (!$param->{directory
}) {
114 die "Aborting.\n" if $attempts > 3;
115 $get_dir_selection->();
119 print "\nAttempting to fetch Terms of Service from '$param->{directory}'..\n";
120 my $tos = PVE
::API2
::ACMEAccount-
>get_tos({ directory
=> $param->{directory
} });
122 print "Terms of Service: $tos\n";
123 my $term = Term
::ReadLine-
>new('pvenode');
124 my $agreed = $term->readline('Do you agree to the above terms? [y|N]: ');
125 die "Cannot continue without agreeing to ToS, aborting.\n"
126 if ($agreed !~ /^y$/i);
128 $param->{tos_url
} = $tos;
130 print "No Terms of Service found, proceeding.\n";
132 print "\nAttempting to register account with '$param->{directory}'..\n";
134 $upid_exit->(PVE
::API2
::ACMEAccount-
>register_account($param));
137 my $print_cert_info = sub {
138 my ($schema, $cert, $options) = @_;
140 my $order = [qw(filename fingerprint subject issuer notbefore notafter public-key-type public-key-bits san)];
141 PVE
::CLIFormatter
::print_api_result
(
142 $cert, $schema, $order, { %$options, noheader
=> 1, sort_key
=> 0 });
147 get
=> [ 'PVE::API2::NodeConfig', 'get_config', [], { node
=> $nodename }, sub {
149 print PVE
::NodeConfig
::write_node_config
($res);
151 set
=> [ 'PVE::API2::NodeConfig', 'set_options', [], { node
=> $nodename } ],
154 startall
=> [ 'PVE::API2::Nodes::Nodeinfo', 'startall', [], { node
=> $nodename } ],
155 stopall
=> [ 'PVE::API2::Nodes::Nodeinfo', 'stopall', [], { node
=> $nodename } ],
156 migrateall
=> [ 'PVE::API2::Nodes::Nodeinfo', 'migrateall', [ 'target' ], { node
=> $nodename } ],
159 info
=> [ 'PVE::API2::Certificates', 'info', [], { node
=> $nodename }, sub {
160 my ($res, $schema, $options) = @_;
162 if (!$options->{'output-format'} || $options->{'output-format'} eq 'text') {
163 for my $cert (sort { $a->{filename
} cmp $b->{filename
} } @$res) {
164 $print_cert_info->($schema->{items
}, $cert, $options);
167 PVE
::CLIFormatter
::print_api_result
($res, $schema, undef, $options);
170 }, $PVE::RESTHandler
::standard_output_options
],
171 set
=> [ 'PVE::API2::Certificates', 'upload_custom_cert', ['certificates', 'key'], { node
=> $nodename }, sub {
172 my ($res, $schema, $options) = @_;
173 $print_cert_info->($schema, $res, $options);
174 }, $PVE::RESTHandler
::standard_output_options
],
175 delete => [ 'PVE::API2::Certificates', 'remove_custom_cert', ['restart'], { node
=> $nodename } ],
179 list
=> [ 'PVE::API2::Tasks', 'node_tasks', [], { node
=> $nodename }, sub {
180 my ($data, $schema, $options) = @_;
181 foreach my $task (@$data) {
182 if (!defined($task->{status
})) {
183 $task->{status
} = 'UNKNOWN';
184 # RUNNING is set by the API call and needs to be checked explicitly
185 } elsif (PVE
::Tools
::upid_status_is_error
($task->{status
}) &&
186 $task->{status
} ne 'RUNNING')
188 $task->{status
} = 'ERROR';
191 PVE
::CLIFormatter
::print_api_result
($data, $schema, ['upid', 'type', 'id', 'user', 'starttime', 'endtime', 'status' ], $options);
192 }, $PVE::RESTHandler
::standard_output_options
],
193 status
=> [ 'PVE::API2::Tasks', 'read_task_status', [ 'upid' ], { node
=> $nodename }, sub {
194 my ($data, $schema, $options) = @_;
195 PVE
::CLIFormatter
::print_api_result
($data, $schema, undef, $options);
196 }, $PVE::RESTHandler
::standard_output_options
],
197 # set limit to 1000000, so we see the whole log, not only the first 50 lines by default
198 log => [ 'PVE::API2::Tasks', 'read_task_log', [ 'upid' ], { node
=> $nodename, limit
=> 1000000 }, sub {
199 my ($data, $resultprops) = @_;
200 foreach my $line (@$data) {
201 print $line->{t
} . "\n";
208 list
=> [ 'PVE::API2::ACMEAccount', 'account_index', [], {}, sub {
210 for my $acc (@$res) {
211 print "$acc->{name}\n";
214 register
=> [ __PACKAGE__
, 'acme_register', ['name', 'contact'], {}, $upid_exit ],
215 deactivate
=> [ 'PVE::API2::ACMEAccount', 'deactivate_account', ['name'], {}, $upid_exit ],
216 info
=> [ 'PVE::API2::ACMEAccount', 'get_account', ['name'], {}, sub {
217 my ($data, $schema, $options) = @_;
218 PVE
::CLIFormatter
::print_api_result
($data, $schema, undef, $options);
219 }, $PVE::RESTHandler
::standard_output_options
],
220 update
=> [ 'PVE::API2::ACMEAccount', 'update_account', ['name'], {}, $upid_exit ],
223 order
=> [ 'PVE::API2::ACME', 'new_certificate', [], { node
=> $nodename }, $upid_exit ],
224 renew
=> [ 'PVE::API2::ACME', 'renew_certificate', [], { node
=> $nodename }, $upid_exit ],
225 revoke
=> [ 'PVE::API2::ACME', 'revoke_certificate', [], { node
=> $nodename }, $upid_exit ],
228 list
=> [ 'PVE::API2::ACMEPlugin', 'index', [], {}, sub {
229 my ($data, $schema, $options) = @_;
230 PVE
::CLIFormatter
::print_api_result
($data, $schema, undef, $options);
231 }, $PVE::RESTHandler
::standard_output_options
],
232 config
=> [ 'PVE::API2::ACMEPlugin', 'get_plugin_config', ['id'], {}, sub {
233 my ($data, $schema, $options) = @_;
234 PVE
::CLIFormatter
::print_api_result
($data, $schema, undef, $options);
235 }, $PVE::RESTHandler
::standard_output_options
],
236 add
=> [ 'PVE::API2::ACMEPlugin', 'add_plugin', ['type', 'id'] ],
237 set
=> [ 'PVE::API2::ACMEPlugin', 'update_plugin', ['id'] ],
238 remove
=> [ 'PVE::API2::ACMEPlugin', 'delete_plugin', ['id'] ],
243 wakeonlan
=> [ 'PVE::API2::Nodes::Nodeinfo', 'wakeonlan', [ 'node' ], {}, sub {
246 print "Wake on LAN packet send for '$mac_addr'\n";