1 package PVE
::API2
::Subscription
;
5 use Digest
::MD5
qw(md5_hex md5_base64);
11 use Proxmox
::RS
::Subscription
;
15 use PVE
::Exception
qw(raise_param_exc);
17 use PVE
::Cluster qw
(cfs_read_file cfs_write_file
);
18 use PVE
::DataCenterConfig
;
19 use PVE
::AccessControl
;
21 use PVE
::JSONSchema
qw(get_standard_option);
28 use base
qw(PVE::RESTHandler);
30 my $subscription_pattern = 'pve([1248])([cbsp])-[0-9a-f]{10}';
31 my $filename = "/etc/subscription";
34 my $info = PVE
::ProcFSTools
::read_cpuinfo
();
35 return $info->{sockets
};
39 my ($key, $noerr) = @_;
41 if ($key =~ m/^${subscription_pattern}$/) {
42 return wantarray ?
($1, $2) : $1; # number of sockets, level
44 return undef if $noerr;
46 die "Wrong subscription key format\n";
50 my ($key, $req_sockets) = @_;
52 my ($sockets, $level) = parse_key
($key);
53 if ($sockets < $req_sockets) {
54 die "wrong number of sockets ($sockets < $req_sockets)\n";
56 return ($sockets, $level);
59 sub read_etc_subscription
{
60 my $req_sockets = get_sockets
();
61 my $server_id = PVE
::API2Tools
::get_hwaddress
();
63 my $info = Proxmox
::RS
::Subscription
::read_subscription
($filename);
65 return $info if !$info || $info->{status
} ne 'active';
67 my ($sockets, $level);
68 eval { ($sockets, $level) = check_key
($info->{key
}, $req_sockets); };
71 $info->{status
} = 'invalid';
72 $info->{message
} = $err;
74 $info->{level
} = $level;
80 sub write_etc_subscription
{
83 my $server_id = PVE
::API2Tools
::get_hwaddress
();
84 mkdir "/etc/apt/auth.conf.d";
85 Proxmox
::RS
::Subscription
::write_subscription
($filename, "/etc/apt/auth.conf.d/pve.conf", "enterprise.proxmox.com/debian/pve", $info);
87 # NOTE: preparation for easier upgrade to Proxmox VE 8, which introduced the ceph enterprise repo
89 for my $ceph_release ('quincy', 'reef') {
90 $ceph_auth .= "machine enterprise.proxmox.com/debian/ceph-${ceph_release}"
91 ." login $info->{key} password $info->{serverid}\n"
93 PVE
::Tools
::file_set_contents
("/etc/apt/auth.conf.d/ceph.conf", $ceph_auth);
96 __PACKAGE__-
>register_method ({
100 description
=> "Read subscription info.",
102 permissions
=> { user
=> 'all' },
104 additionalProperties
=> 0,
106 node
=> get_standard_option
('pve-node'),
109 returns
=> { type
=> 'object'},
113 my $node = $param->{node
};
115 my $rpcenv = PVE
::RPCEnvironment
::get
();
116 my $authuser = $rpcenv->get_user();
117 my $has_permission = $rpcenv->check($authuser, "/nodes/$node", ['Sys.Audit'], 1);
119 my $server_id = PVE
::API2Tools
::get_hwaddress
();
120 my $url = "https://www.proxmox.com/proxmox-ve/pricing";
122 my $info = read_etc_subscription
();
124 my $no_subscription_info = {
125 status
=> "notfound",
126 message
=> "There is no subscription key",
129 $no_subscription_info->{serverid
} = $server_id if $has_permission;
130 return $no_subscription_info;
133 if (!$has_permission) {
135 status
=> $info->{status
},
136 message
=> $info->{message
},
141 $info->{serverid
} = $server_id;
142 $info->{sockets
} = get_sockets
();
148 __PACKAGE__-
>register_method ({
153 check
=> ['perm', '/nodes/{node}', [ 'Sys.Modify' ]],
155 description
=> "Update subscription info.",
159 additionalProperties
=> 0,
161 node
=> get_standard_option
('pve-node'),
163 description
=> "Always connect to server, even if we have up to date info inside local cache.",
170 returns
=> { type
=> 'null'},
174 my $info = read_etc_subscription
();
175 return undef if !$info;
177 my $server_id = PVE
::API2Tools
::get_hwaddress
();
178 my $key = $info->{key
};
180 die "Updating offline key not possible - please remove and re-add subscription key to switch to online key.\n"
181 if $info->{signature
};
183 # key has been recently checked
186 && $info->{status
} eq 'active'
187 && Proxmox
::RS
::Subscription
::check_age
($info, 1)->{status
} eq 'active';
189 my $req_sockets = get_sockets
();
190 check_key
($key, $req_sockets);
192 my $dccfg = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
193 my $proxy = $dccfg->{http_proxy
};
195 $info = Proxmox
::RS
::Subscription
::check_subscription
($key, $server_id, "", "Proxmox VE", $proxy);
197 write_etc_subscription
($info);
202 __PACKAGE__-
>register_method ({
207 check
=> ['perm', '/nodes/{node}', [ 'Sys.Modify' ]],
209 description
=> "Set subscription key.",
213 additionalProperties
=> 0,
215 node
=> get_standard_option
('pve-node'),
217 description
=> "Proxmox VE subscription key",
219 pattern
=> $subscription_pattern,
224 returns
=> { type
=> 'null'},
228 my $key = PVE
::Tools
::trim
($param->{key
});
236 my $req_sockets = get_sockets
();
237 my $server_id = PVE
::API2Tools
::get_hwaddress
();
239 check_key
($key, $req_sockets);
241 write_etc_subscription
($info);
243 my $dccfg = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
244 my $proxy = $dccfg->{http_proxy
};
246 $info = Proxmox
::RS
::Subscription
::check_subscription
($key, $server_id, "", "Proxmox VE", $proxy);
248 write_etc_subscription
($info);
253 __PACKAGE__-
>register_method ({
258 check
=> ['perm', '/nodes/{node}', [ 'Sys.Modify' ]],
260 description
=> "Delete subscription key of this node.",
264 additionalProperties
=> 0,
266 node
=> get_standard_option
('pve-node'),
269 returns
=> { type
=> 'null'},
271 my $subscription_file = '/etc/subscription';
272 return if ! -e
$subscription_file;
273 unlink($subscription_file) or die "cannot delete subscription key: $!";