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 my sub cache_is_valid
{
83 return if !$info || $info->{status
} ne 'active';
85 my $checked_info = Proxmox
::RS
::Subscription
::check_age
($info, 1);
86 return $checked_info->{status
} eq 'active'
89 sub write_etc_subscription
{
92 my $server_id = PVE
::API2Tools
::get_hwaddress
();
93 mkdir "/etc/apt/auth.conf.d";
94 Proxmox
::RS
::Subscription
::write_subscription
(
95 $filename, "/etc/apt/auth.conf.d/pve.conf", "enterprise.proxmox.com/debian/pve", $info);
97 # FIXME: improve this, especially the selection of valid ceph-releases
98 # NOTE: currently we should add future ceph releases as early as possible, to ensure that
100 for my $ceph_release ('quincy', 'reef') {
101 $ceph_auth .= "machine enterprise.proxmox.com/debian/ceph-${ceph_release}"
102 ." login $info->{key} password $info->{serverid}\n"
104 PVE
::Tools
::file_set_contents
("/etc/apt/auth.conf.d/ceph.conf", $ceph_auth);
107 __PACKAGE__-
>register_method ({
111 description
=> "Read subscription info.",
113 permissions
=> { user
=> 'all' },
115 additionalProperties
=> 0,
117 node
=> get_standard_option
('pve-node'),
120 returns
=> { type
=> 'object'},
124 my $node = $param->{node
};
126 my $rpcenv = PVE
::RPCEnvironment
::get
();
127 my $authuser = $rpcenv->get_user();
128 my $has_permission = $rpcenv->check($authuser, "/nodes/$node", ['Sys.Audit'], 1);
130 my $server_id = PVE
::API2Tools
::get_hwaddress
();
131 my $url = "https://www.proxmox.com/proxmox-ve/pricing";
133 my $info = read_etc_subscription
();
135 my $no_subscription_info = {
136 status
=> "notfound",
137 message
=> "There is no subscription key",
140 $no_subscription_info->{serverid
} = $server_id if $has_permission;
141 return $no_subscription_info;
144 if (!$has_permission) {
146 status
=> $info->{status
},
147 message
=> $info->{message
},
152 $info->{serverid
} = $server_id;
153 $info->{sockets
} = get_sockets
();
159 __PACKAGE__-
>register_method ({
164 check
=> ['perm', '/nodes/{node}', [ 'Sys.Modify' ]],
166 description
=> "Update subscription info.",
170 additionalProperties
=> 0,
172 node
=> get_standard_option
('pve-node'),
174 description
=> "Always connect to server, even if local cache is still valid.",
181 returns
=> { type
=> 'null'},
185 my $info = read_etc_subscription
();
186 return undef if !$info;
188 my $server_id = PVE
::API2Tools
::get_hwaddress
();
189 my $key = $info->{key
};
191 die "Updating offline key not possible - please remove and re-add subscription key to switch to online key.\n"
192 if $info->{signature
};
194 return undef if !$param->{force
} && cache_is_valid
($info); # key has been recently checked
196 my $req_sockets = get_sockets
();
197 check_key
($key, $req_sockets);
199 my $dccfg = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
200 my $proxy = $dccfg->{http_proxy
};
202 $info = Proxmox
::RS
::Subscription
::check_subscription
($key, $server_id, "", "Proxmox VE", $proxy);
204 write_etc_subscription
($info);
209 __PACKAGE__-
>register_method ({
214 check
=> ['perm', '/nodes/{node}', [ 'Sys.Modify' ]],
216 description
=> "Set subscription key.",
220 additionalProperties
=> 0,
222 node
=> get_standard_option
('pve-node'),
224 description
=> "Proxmox VE subscription key",
226 pattern
=> $subscription_pattern,
231 returns
=> { type
=> 'null'},
235 my $key = PVE
::Tools
::trim
($param->{key
});
243 my $req_sockets = get_sockets
();
244 my $server_id = PVE
::API2Tools
::get_hwaddress
();
246 check_key
($key, $req_sockets);
248 write_etc_subscription
($new_info);
250 my $dccfg = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
251 my $proxy = $dccfg->{http_proxy
};
253 my $checked_info = Proxmox
::RS
::Subscription
::check_subscription
(
254 $key, $server_id, "", "Proxmox VE", $proxy);
256 write_etc_subscription
($checked_info);
261 __PACKAGE__-
>register_method ({
266 check
=> ['perm', '/nodes/{node}', [ 'Sys.Modify' ]],
268 description
=> "Delete subscription key of this node.",
272 additionalProperties
=> 0,
274 node
=> get_standard_option
('pve-node'),
277 returns
=> { type
=> 'null'},
279 my $subscription_file = '/etc/subscription';
280 return if ! -e
$subscription_file;
281 unlink($subscription_file) or die "cannot delete subscription key: $!";