]> git.proxmox.com Git - pve-manager.git/blame - PVE/API2/Subscription.pm
api: add proxmox-firewall to versions pkg list
[pve-manager.git] / PVE / API2 / Subscription.pm
CommitLineData
21ace8d3
DM
1package PVE::API2::Subscription;
2
3use strict;
4use warnings;
5use Digest::MD5 qw(md5_hex md5_base64);
6use MIME::Base64;
7use HTTP::Request;
8use LWP::UserAgent;
43fc27a4 9use JSON;
21ace8d3 10
d017de1f
FG
11use Proxmox::RS::Subscription;
12
21ace8d3 13use PVE::Tools;
8f9217dc 14use PVE::ProcFSTools;
21ace8d3
DM
15use PVE::Exception qw(raise_param_exc);
16use PVE::INotify;
17use PVE::Cluster qw (cfs_read_file cfs_write_file);
3ac3653e 18use PVE::DataCenterConfig;
21ace8d3
DM
19use PVE::AccessControl;
20use PVE::Storage;
21use PVE::JSONSchema qw(get_standard_option);
22
23use PVE::SafeSyslog;
24
25use PVE::API2Tools;
26use PVE::RESTHandler;
27
28use base qw(PVE::RESTHandler);
29
9fdfebf7 30my $subscription_pattern = 'pve([1248])([cbsp])-[0-9a-f]{10}';
d017de1f 31my $filename = "/etc/subscription";
21ace8d3 32
21ace8d3 33sub get_sockets {
8f9217dc
DM
34 my $info = PVE::ProcFSTools::read_cpuinfo();
35 return $info->{sockets};
21ace8d3
DM
36}
37
38sub parse_key {
43fc27a4 39 my ($key, $noerr) = @_;
21ace8d3 40
43fc27a4 41 if ($key =~ m/^${subscription_pattern}$/) {
16b69b6c 42 return wantarray ? ($1, $2) : $1; # number of sockets, level
21ace8d3 43 }
43fc27a4
DM
44 return undef if $noerr;
45
46 die "Wrong subscription key format\n";
21ace8d3
DM
47}
48
43fc27a4
DM
49sub check_key {
50 my ($key, $req_sockets) = @_;
21ace8d3 51
43fc27a4 52 my ($sockets, $level) = parse_key($key);
21ace8d3
DM
53 if ($sockets < $req_sockets) {
54 die "wrong number of sockets ($sockets < $req_sockets)\n";
55 }
43fc27a4 56 return ($sockets, $level);
21ace8d3
DM
57}
58
d017de1f 59sub read_etc_subscription {
43fc27a4
DM
60 my $req_sockets = get_sockets();
61 my $server_id = PVE::API2Tools::get_hwaddress();
21ace8d3 62
d017de1f 63 my $info = Proxmox::RS::Subscription::read_subscription($filename);
21ace8d3 64
25eaf729 65 return $info if !$info || $info->{status} ne 'active';
21ace8d3 66
43fc27a4
DM
67 my ($sockets, $level);
68 eval { ($sockets, $level) = check_key($info->{key}, $req_sockets); };
69 if (my $err = $@) {
70 chomp $err;
d017de1f 71 $info->{status} = 'invalid';
43fc27a4
DM
72 $info->{message} = $err;
73 } else {
16b69b6c
DM
74 $info->{level} = $level;
75 }
76
21ace8d3
DM
77 return $info;
78}
79
fc3e061b
TL
80my sub cache_is_valid {
81 my ($info) = @_;
82
83 return if !$info || $info->{status} ne 'active';
84
85 my $checked_info = Proxmox::RS::Subscription::check_age($info, 1);
86 return $checked_info->{status} eq 'active'
87}
88
d017de1f
FG
89sub write_etc_subscription {
90 my ($info) = @_;
21ace8d3 91
2ba6d822 92 my $server_id = PVE::API2Tools::get_hwaddress();
d017de1f 93 mkdir "/etc/apt/auth.conf.d";
76a165a1
TL
94 Proxmox::RS::Subscription::write_subscription(
95 $filename, "/etc/apt/auth.conf.d/pve.conf", "enterprise.proxmox.com/debian/pve", $info);
93542d77 96
506134df
FG
97 if (!(defined($info->{key}) && defined($info->{serverid}))) {
98 unlink "/etc/apt/auth.conf.d/ceph.conf";
99 } else {
100 # FIXME: improve this, especially the selection of valid ceph-releases
101 # NOTE: currently we should add future ceph releases as early as possible, to ensure that
102 my $ceph_auth = '';
103 for my $ceph_release ('quincy', 'reef') {
104 $ceph_auth .= "machine enterprise.proxmox.com/debian/ceph-${ceph_release}"
93542d77 105 ." login $info->{key} password $info->{serverid}\n"
506134df
FG
106 }
107 PVE::Tools::file_set_contents("/etc/apt/auth.conf.d/ceph.conf", $ceph_auth);
93542d77 108 }
21ace8d3
DM
109}
110
111__PACKAGE__->register_method ({
43fc27a4
DM
112 name => 'get',
113 path => '',
21ace8d3
DM
114 method => 'GET',
115 description => "Read subscription info.",
116 proxyto => 'node',
e721a829 117 permissions => { user => 'all' },
21ace8d3
DM
118 parameters => {
119 additionalProperties => 0,
120 properties => {
121 node => get_standard_option('pve-node'),
122 },
123 },
124 returns => { type => 'object'},
125 code => sub {
126 my ($param) = @_;
127
7d6fba8f 128 my $node = $param->{node};
00a93a4b 129
2d2ed7ab
DM
130 my $rpcenv = PVE::RPCEnvironment::get();
131 my $authuser = $rpcenv->get_user();
d8645329 132 my $has_permission = $rpcenv->check($authuser, "/nodes/$node", ['Sys.Audit'], 1);
2d2ed7ab 133
7d762f4c 134 my $server_id = PVE::API2Tools::get_hwaddress();
347f88fe 135 my $url = "https://www.proxmox.com/en/proxmox-virtual-environment/pricing";
7d762f4c 136
d017de1f 137 my $info = read_etc_subscription();
21ace8d3 138 if (!$info) {
2d2ed7ab 139 my $no_subscription_info = {
d017de1f 140 status => "notfound",
21ace8d3 141 message => "There is no subscription key",
2d2ed7ab
DM
142 url => $url,
143 };
144 $no_subscription_info->{serverid} = $server_id if $has_permission;
145 return $no_subscription_info;
146 }
147
148 if (!$has_permission) {
149 return {
150 status => $info->{status},
151 message => $info->{message},
43fc27a4 152 url => $url,
21ace8d3
DM
153 }
154 }
00a93a4b
DM
155
156 $info->{serverid} = $server_id;
157 $info->{sockets} = get_sockets();
43fc27a4 158 $info->{url} = $url;
00a93a4b 159
21ace8d3
DM
160 return $info
161 }});
162
163__PACKAGE__->register_method ({
43fc27a4
DM
164 name => 'update',
165 path => '',
21ace8d3 166 method => 'POST',
69bbb885
TL
167 permissions => {
168 check => ['perm', '/nodes/{node}', [ 'Sys.Modify' ]],
169 },
21ace8d3
DM
170 description => "Update subscription info.",
171 proxyto => 'node',
172 protected => 1,
173 parameters => {
174 additionalProperties => 0,
175 properties => {
176 node => get_standard_option('pve-node'),
177 force => {
76a165a1 178 description => "Always connect to server, even if local cache is still valid.",
21ace8d3
DM
179 type => 'boolean',
180 optional => 1,
181 default => 0
182 }
183 },
184 },
185 returns => { type => 'null'},
186 code => sub {
187 my ($param) = @_;
188
d017de1f 189 my $info = read_etc_subscription();
21ace8d3
DM
190 return undef if !$info;
191
43fc27a4
DM
192 my $server_id = PVE::API2Tools::get_hwaddress();
193 my $key = $info->{key};
194
d4df1b14
FG
195 die "Updating offline key not possible - please remove and re-add subscription key to switch to online key.\n"
196 if $info->{signature};
197
fc3e061b 198 return undef if !$param->{force} && cache_is_valid($info); # key has been recently checked
21ace8d3 199
43fc27a4
DM
200 my $req_sockets = get_sockets();
201 check_key($key, $req_sockets);
202
203 my $dccfg = PVE::Cluster::cfs_read_file('datacenter.cfg');
204 my $proxy = $dccfg->{http_proxy};
205
d017de1f 206 $info = Proxmox::RS::Subscription::check_subscription($key, $server_id, "", "Proxmox VE", $proxy);
21ace8d3 207
d017de1f 208 write_etc_subscription($info);
21ace8d3
DM
209
210 return undef;
211 }});
212
213__PACKAGE__->register_method ({
43fc27a4
DM
214 name => 'set',
215 path => '',
21ace8d3 216 method => 'PUT',
69bbb885
TL
217 permissions => {
218 check => ['perm', '/nodes/{node}', [ 'Sys.Modify' ]],
219 },
21ace8d3
DM
220 description => "Set subscription key.",
221 proxyto => 'node',
222 protected => 1,
223 parameters => {
e82ed167 224 additionalProperties => 0,
21ace8d3
DM
225 properties => {
226 node => get_standard_option('pve-node'),
227 key => {
228 description => "Proxmox VE subscription key",
229 type => 'string',
b7588bcd 230 pattern => "\\s*${subscription_pattern}\\s*",
43fc27a4 231 maxLength => 32,
21ace8d3
DM
232 },
233 },
234 },
235 returns => { type => 'null'},
236 code => sub {
237 my ($param) = @_;
238
43fc27a4 239 my $key = PVE::Tools::trim($param->{key});
94cc9560 240
76a165a1 241 my $new_info = {
21ace8d3 242 status => 'New',
43fc27a4 243 key => $key,
21ace8d3
DM
244 checktime => time(),
245 };
246
247 my $req_sockets = get_sockets();
2ba6d822 248 my $server_id = PVE::API2Tools::get_hwaddress();
21ace8d3 249
43fc27a4 250 check_key($key, $req_sockets);
21ace8d3 251
76a165a1 252 write_etc_subscription($new_info);
21ace8d3 253
43fc27a4
DM
254 my $dccfg = PVE::Cluster::cfs_read_file('datacenter.cfg');
255 my $proxy = $dccfg->{http_proxy};
256
76a165a1
TL
257 my $checked_info = Proxmox::RS::Subscription::check_subscription(
258 $key, $server_id, "", "Proxmox VE", $proxy);
21ace8d3 259
76a165a1 260 write_etc_subscription($checked_info);
21ace8d3
DM
261
262 return undef;
263 }});
264
85222f82
MA
265__PACKAGE__->register_method ({
266 name => 'delete',
267 path => '',
268 method => 'DELETE',
269 permissions => {
270 check => ['perm', '/nodes/{node}', [ 'Sys.Modify' ]],
271 },
bc12fba5 272 description => "Delete subscription key of this node.",
85222f82
MA
273 proxyto => 'node',
274 protected => 1,
275 parameters => {
e82ed167 276 additionalProperties => 0,
85222f82
MA
277 properties => {
278 node => get_standard_option('pve-node'),
279 },
280 },
281 returns => { type => 'null'},
282 code => sub {
283 my $subscription_file = '/etc/subscription';
e82ed167 284 return if ! -e $subscription_file;
85222f82
MA
285 unlink($subscription_file) or die "cannot delete subscription key: $!";
286 return undef;
287 }});
288
21ace8d3 2891;