]> git.proxmox.com Git - pve-manager.git/blame - PVE/API2/Subscription.pm
bump version to 5.4-15
[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
DM
10
11use PVE::Tools;
8f9217dc 12use PVE::ProcFSTools;
21ace8d3
DM
13use PVE::Exception qw(raise_param_exc);
14use PVE::INotify;
15use PVE::Cluster qw (cfs_read_file cfs_write_file);
16use PVE::AccessControl;
17use PVE::Storage;
18use PVE::JSONSchema qw(get_standard_option);
19
20use PVE::SafeSyslog;
43fc27a4 21use PVE::Subscription;
21ace8d3
DM
22
23use PVE::API2Tools;
24use PVE::RESTHandler;
25
26use base qw(PVE::RESTHandler);
27
5f7b7950 28PVE::INotify::register_file('subscription', "/etc/subscription",
21ace8d3
DM
29 \&read_etc_pve_subscription,
30 \&write_etc_pve_subscription);
31
9fdfebf7 32my $subscription_pattern = 'pve([1248])([cbsp])-[0-9a-f]{10}';
21ace8d3 33
21ace8d3 34sub get_sockets {
8f9217dc
DM
35 my $info = PVE::ProcFSTools::read_cpuinfo();
36 return $info->{sockets};
21ace8d3
DM
37}
38
39sub parse_key {
43fc27a4 40 my ($key, $noerr) = @_;
21ace8d3 41
43fc27a4 42 if ($key =~ m/^${subscription_pattern}$/) {
16b69b6c 43 return wantarray ? ($1, $2) : $1; # number of sockets, level
21ace8d3 44 }
43fc27a4
DM
45 return undef if $noerr;
46
47 die "Wrong subscription key format\n";
21ace8d3
DM
48}
49
43fc27a4
DM
50sub check_key {
51 my ($key, $req_sockets) = @_;
21ace8d3 52
43fc27a4 53 my ($sockets, $level) = parse_key($key);
21ace8d3
DM
54 if ($sockets < $req_sockets) {
55 die "wrong number of sockets ($sockets < $req_sockets)\n";
56 }
43fc27a4 57 return ($sockets, $level);
21ace8d3
DM
58}
59
60sub read_etc_pve_subscription {
61 my ($filename, $fh) = @_;
62
43fc27a4
DM
63 my $req_sockets = get_sockets();
64 my $server_id = PVE::API2Tools::get_hwaddress();
21ace8d3 65
43fc27a4 66 my $info = PVE::Subscription::read_subscription($server_id, $filename, $fh);
21ace8d3 67
43fc27a4 68 return $info if $info->{status} ne 'Active';
21ace8d3 69
43fc27a4
DM
70 my ($sockets, $level);
71 eval { ($sockets, $level) = check_key($info->{key}, $req_sockets); };
72 if (my $err = $@) {
73 chomp $err;
74 $info->{status} = 'Invalid';
75 $info->{message} = $err;
76 } else {
16b69b6c
DM
77 $info->{level} = $level;
78 }
79
21ace8d3
DM
80 return $info;
81}
82
83sub write_etc_pve_subscription {
84 my ($filename, $fh, $info) = @_;
85
2ba6d822 86 my $server_id = PVE::API2Tools::get_hwaddress();
43fc27a4 87 PVE::Subscription::write_subscription($server_id, $filename, $fh, $info);
21ace8d3
DM
88}
89
90__PACKAGE__->register_method ({
43fc27a4
DM
91 name => 'get',
92 path => '',
21ace8d3
DM
93 method => 'GET',
94 description => "Read subscription info.",
95 proxyto => 'node',
e721a829 96 permissions => { user => 'all' },
21ace8d3
DM
97 parameters => {
98 additionalProperties => 0,
99 properties => {
100 node => get_standard_option('pve-node'),
101 },
102 },
103 returns => { type => 'object'},
104 code => sub {
105 my ($param) = @_;
106
7d6fba8f 107 my $node = $param->{node};
00a93a4b 108
2d2ed7ab
DM
109 my $rpcenv = PVE::RPCEnvironment::get();
110 my $authuser = $rpcenv->get_user();
7d6fba8f 111 my $has_permission = PVE::AccessControl::check_permissions($authuser, "/nodes/$node", 'Sys.Audit');
2d2ed7ab 112
7d762f4c
TL
113 my $server_id = PVE::API2Tools::get_hwaddress();
114 my $url = "http://www.proxmox.com/products/proxmox-ve/subscription-service-plans";
115
21ace8d3
DM
116 my $info = PVE::INotify::read_file('subscription');
117 if (!$info) {
2d2ed7ab 118 my $no_subscription_info = {
21ace8d3
DM
119 status => "NotFound",
120 message => "There is no subscription key",
2d2ed7ab
DM
121 url => $url,
122 };
123 $no_subscription_info->{serverid} = $server_id if $has_permission;
124 return $no_subscription_info;
125 }
126
127 if (!$has_permission) {
128 return {
129 status => $info->{status},
130 message => $info->{message},
43fc27a4 131 url => $url,
21ace8d3
DM
132 }
133 }
00a93a4b
DM
134
135 $info->{serverid} = $server_id;
136 $info->{sockets} = get_sockets();
43fc27a4 137 $info->{url} = $url;
00a93a4b 138
21ace8d3
DM
139 return $info
140 }});
141
142__PACKAGE__->register_method ({
43fc27a4
DM
143 name => 'update',
144 path => '',
21ace8d3 145 method => 'POST',
69bbb885
TL
146 permissions => {
147 check => ['perm', '/nodes/{node}', [ 'Sys.Modify' ]],
148 },
21ace8d3
DM
149 description => "Update subscription info.",
150 proxyto => 'node',
151 protected => 1,
152 parameters => {
153 additionalProperties => 0,
154 properties => {
155 node => get_standard_option('pve-node'),
156 force => {
157 description => "Always connect to server, even if we have up to date info inside local cache.",
158 type => 'boolean',
159 optional => 1,
160 default => 0
161 }
162 },
163 },
164 returns => { type => 'null'},
165 code => sub {
166 my ($param) = @_;
167
168 my $info = PVE::INotify::read_file('subscription');
169 return undef if !$info;
170
43fc27a4
DM
171 my $server_id = PVE::API2Tools::get_hwaddress();
172 my $key = $info->{key};
173
174 if ($key) {
175 PVE::Subscription::update_apt_auth($key, $server_id);
176 }
7b02d9ec 177
21ace8d3
DM
178 if (!$param->{force} && $info->{status} eq 'Active') {
179 my $age = time() - $info->{checktime};
43fc27a4 180 return undef if $age < $PVE::Subscription::localkeydays*60*60*24;
21ace8d3 181 }
21ace8d3 182
43fc27a4
DM
183 my $req_sockets = get_sockets();
184 check_key($key, $req_sockets);
185
186 my $dccfg = PVE::Cluster::cfs_read_file('datacenter.cfg');
187 my $proxy = $dccfg->{http_proxy};
188
189 $info = PVE::Subscription::check_subscription($key, $server_id, $proxy);
21ace8d3
DM
190
191 PVE::INotify::write_file('subscription', $info);
192
193 return undef;
194 }});
195
196__PACKAGE__->register_method ({
43fc27a4
DM
197 name => 'set',
198 path => '',
21ace8d3 199 method => 'PUT',
69bbb885
TL
200 permissions => {
201 check => ['perm', '/nodes/{node}', [ 'Sys.Modify' ]],
202 },
21ace8d3
DM
203 description => "Set subscription key.",
204 proxyto => 'node',
205 protected => 1,
206 parameters => {
207 additionalProperties => 0,
208 properties => {
209 node => get_standard_option('pve-node'),
210 key => {
211 description => "Proxmox VE subscription key",
212 type => 'string',
43fc27a4
DM
213 pattern => $subscription_pattern,
214 maxLength => 32,
21ace8d3
DM
215 },
216 },
217 },
218 returns => { type => 'null'},
219 code => sub {
220 my ($param) = @_;
221
43fc27a4 222 my $key = PVE::Tools::trim($param->{key});
94cc9560 223
21ace8d3
DM
224 my $info = {
225 status => 'New',
43fc27a4 226 key => $key,
21ace8d3
DM
227 checktime => time(),
228 };
229
230 my $req_sockets = get_sockets();
2ba6d822 231 my $server_id = PVE::API2Tools::get_hwaddress();
21ace8d3 232
43fc27a4 233 check_key($key, $req_sockets);
21ace8d3
DM
234
235 PVE::INotify::write_file('subscription', $info);
236
43fc27a4
DM
237 my $dccfg = PVE::Cluster::cfs_read_file('datacenter.cfg');
238 my $proxy = $dccfg->{http_proxy};
239
240 $info = PVE::Subscription::check_subscription($key, $server_id, $proxy);
21ace8d3
DM
241
242 PVE::INotify::write_file('subscription', $info);
243
244 return undef;
245 }});
246
2471;