1 package PVE
::API2
::Subscription
;
5 use Digest
::MD5
qw(md5_hex md5_base64);
13 use PVE
::Exception
qw(raise_param_exc);
15 use PVE
::Cluster qw
(cfs_read_file cfs_write_file
);
16 use PVE
::DataCenterConfig
;
17 use PVE
::AccessControl
;
19 use PVE
::JSONSchema
qw(get_standard_option);
22 use PVE
::Subscription
;
27 use base
qw(PVE::RESTHandler);
29 PVE
::INotify
::register_file
('subscription', "/etc/subscription",
30 \
&read_etc_pve_subscription
,
31 \
&write_etc_pve_subscription
);
33 my $subscription_pattern = 'pve([1248])([cbsp])-[0-9a-f]{10}';
36 my $info = PVE
::ProcFSTools
::read_cpuinfo
();
37 return $info->{sockets
};
41 my ($key, $noerr) = @_;
43 if ($key =~ m/^${subscription_pattern}$/) {
44 return wantarray ?
($1, $2) : $1; # number of sockets, level
46 return undef if $noerr;
48 die "Wrong subscription key format\n";
52 my ($key, $req_sockets) = @_;
54 my ($sockets, $level) = parse_key
($key);
55 if ($sockets < $req_sockets) {
56 die "wrong number of sockets ($sockets < $req_sockets)\n";
58 return ($sockets, $level);
61 sub read_etc_pve_subscription
{
62 my ($filename, $fh) = @_;
64 my $req_sockets = get_sockets
();
65 my $server_id = PVE
::API2Tools
::get_hwaddress
();
67 my $info = PVE
::Subscription
::read_subscription
($server_id, $filename, $fh);
69 return $info if $info->{status
} ne 'Active';
71 my ($sockets, $level);
72 eval { ($sockets, $level) = check_key
($info->{key
}, $req_sockets); };
75 $info->{status
} = 'Invalid';
76 $info->{message
} = $err;
78 $info->{level
} = $level;
84 sub write_etc_pve_subscription
{
85 my ($filename, $fh, $info) = @_;
87 my $server_id = PVE
::API2Tools
::get_hwaddress
();
88 PVE
::Subscription
::write_subscription
($server_id, $filename, $fh, $info);
91 __PACKAGE__-
>register_method ({
95 description
=> "Read subscription info.",
97 permissions
=> { user
=> 'all' },
99 additionalProperties
=> 0,
101 node
=> get_standard_option
('pve-node'),
104 returns
=> { type
=> 'object'},
108 my $node = $param->{node
};
110 my $rpcenv = PVE
::RPCEnvironment
::get
();
111 my $authuser = $rpcenv->get_user();
112 my $has_permission = $rpcenv->check($authuser, "/nodes/$node", ['Sys.Audit'], 1);
114 my $server_id = PVE
::API2Tools
::get_hwaddress
();
115 my $url = "https://www.proxmox.com/proxmox-ve/pricing";
117 my $info = PVE
::INotify
::read_file
('subscription');
119 my $no_subscription_info = {
120 status
=> "NotFound",
121 message
=> "There is no subscription key",
124 $no_subscription_info->{serverid
} = $server_id if $has_permission;
125 return $no_subscription_info;
128 if (!$has_permission) {
130 status
=> $info->{status
},
131 message
=> $info->{message
},
136 $info->{serverid
} = $server_id;
137 $info->{sockets
} = get_sockets
();
143 __PACKAGE__-
>register_method ({
148 check
=> ['perm', '/nodes/{node}', [ 'Sys.Modify' ]],
150 description
=> "Update subscription info.",
154 additionalProperties
=> 0,
156 node
=> get_standard_option
('pve-node'),
158 description
=> "Always connect to server, even if we have up to date info inside local cache.",
165 returns
=> { type
=> 'null'},
169 my $info = PVE
::INotify
::read_file
('subscription');
170 return undef if !$info;
172 my $server_id = PVE
::API2Tools
::get_hwaddress
();
173 my $key = $info->{key
};
176 PVE
::Subscription
::update_apt_auth
($key, $server_id);
179 if (!$param->{force
} && $info->{status
} eq 'Active') {
180 my $age = time() - $info->{checktime
};
181 return undef if $age < $PVE::Subscription
::localkeydays
*60*60*24;
184 my $req_sockets = get_sockets
();
185 check_key
($key, $req_sockets);
187 my $dccfg = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
188 my $proxy = $dccfg->{http_proxy
};
190 $info = PVE
::Subscription
::check_subscription
($key, $server_id, $proxy);
192 PVE
::INotify
::write_file
('subscription', $info);
197 __PACKAGE__-
>register_method ({
202 check
=> ['perm', '/nodes/{node}', [ 'Sys.Modify' ]],
204 description
=> "Set subscription key.",
208 additionalProperties
=> 0,
210 node
=> get_standard_option
('pve-node'),
212 description
=> "Proxmox VE subscription key",
214 pattern
=> $subscription_pattern,
219 returns
=> { type
=> 'null'},
223 my $key = PVE
::Tools
::trim
($param->{key
});
231 my $req_sockets = get_sockets
();
232 my $server_id = PVE
::API2Tools
::get_hwaddress
();
234 check_key
($key, $req_sockets);
236 PVE
::INotify
::write_file
('subscription', $info);
238 my $dccfg = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
239 my $proxy = $dccfg->{http_proxy
};
241 $info = PVE
::Subscription
::check_subscription
($key, $server_id, $proxy);
243 PVE
::INotify
::write_file
('subscription', $info);
248 __PACKAGE__-
>register_method ({
253 check
=> ['perm', '/nodes/{node}', [ 'Sys.Modify' ]],
255 description
=> "Delete subscription key.",
259 additionalProperties
=> 0,
261 node
=> get_standard_option
('pve-node'),
264 returns
=> { type
=> 'null'},
266 my $subscription_file = '/etc/subscription';
267 return if ! -e
$subscription_file;
268 unlink($subscription_file) or die "cannot delete subscription key: $!";