]> git.proxmox.com Git - pve-storage.git/blame - PVE/API2/Storage/Config.pm
Add set CIFS credentials.
[pve-storage.git] / PVE / API2 / Storage / Config.pm
CommitLineData
b6cf0a66
DM
1package PVE::API2::Storage::Config;
2
3use strict;
4use warnings;
5
6use PVE::SafeSyslog;
1dc01b9f 7use PVE::Tools qw(extract_param);
b6cf0a66
DM
8use PVE::Cluster qw(cfs_read_file cfs_write_file);
9use PVE::Storage;
1dc01b9f 10use PVE::Storage::Plugin;
b6cf0a66
DM
11use HTTP::Status qw(:constants);
12use Storable qw(dclone);
13use PVE::JSONSchema qw(get_standard_option);
5f642f73 14use PVE::RPCEnvironment;
b6cf0a66
DM
15
16use PVE::RESTHandler;
17
18use base qw(PVE::RESTHandler);
19
20my @ctypes = qw(images vztmpl iso backup);
21
1dc01b9f 22my $storage_type_enum = PVE::Storage::Plugin->lookup_types();
b6cf0a66
DM
23
24my $api_storage_config = sub {
25 my ($cfg, $storeid) = @_;
26
1dc01b9f 27 my $scfg = dclone(PVE::Storage::storage_config($cfg, $storeid));
b6cf0a66 28 $scfg->{storage} = $storeid;
b6cf0a66 29 $scfg->{digest} = $cfg->{digest};
1dc01b9f 30 $scfg->{content} = PVE::Storage::Plugin->encode_value($scfg->{type}, 'content', $scfg->{content});
b6cf0a66
DM
31
32 if ($scfg->{nodes}) {
1dc01b9f 33 $scfg->{nodes} = PVE::Storage::Plugin->encode_value($scfg->{type}, 'nodes', $scfg->{nodes});
b6cf0a66
DM
34 }
35
36 return $scfg;
37};
38
f79a699c
WL
39my $set_cifs_credentials = sub {
40 my ($password, $storeid) = @_;
41
42 my $cred_path = '/etc/pve/priv/';
43
44 my $cred_file = $cred_path.$storeid.".cred";
45
46 PVE::Tools::file_set_contents($cred_file, "password=$password\n");
47
48 return $cred_file;
49};
50
b6cf0a66
DM
51__PACKAGE__->register_method ({
52 name => 'index',
53 path => '',
54 method => 'GET',
55 description => "Storage index.",
5f642f73
DM
56 permissions => {
57 description => "Only list entries where you have 'Datastore.Audit' or 'Datastore.AllocateSpace' permissions on '/storage/<storage>'",
58 user => 'all',
59 },
b6cf0a66
DM
60 parameters => {
61 additionalProperties => 0,
62 properties => {
63 type => {
64 description => "Only list storage of specific type",
65 type => 'string',
66 enum => $storage_type_enum,
67 optional => 1,
68 },
b6cf0a66
DM
69 },
70 },
71 returns => {
72 type => 'array',
73 items => {
74 type => "object",
75 properties => { storage => { type => 'string'} },
76 },
77 links => [ { rel => 'child', href => "{storage}" } ],
78 },
79 code => sub {
80 my ($param) = @_;
81
5f642f73
DM
82 my $rpcenv = PVE::RPCEnvironment::get();
83 my $authuser = $rpcenv->get_user();
84
83d7192f 85 my $cfg = PVE::Storage::config();
b6cf0a66 86
5f642f73 87 my @sids = PVE::Storage::storage_ids($cfg);
b6cf0a66
DM
88
89 my $res = [];
90 foreach my $storeid (@sids) {
5f642f73
DM
91 my $privs = [ 'Datastore.Audit', 'Datastore.AllocateSpace' ];
92 next if !$rpcenv->check_any($authuser, "/storage/$storeid", $privs, 1);
93
b6cf0a66
DM
94 my $scfg = &$api_storage_config($cfg, $storeid);
95 next if $param->{type} && $param->{type} ne $scfg->{type};
96 push @$res, $scfg;
97 }
98
99 return $res;
100 }});
101
102__PACKAGE__->register_method ({
103 name => 'read',
104 path => '{storage}',
105 method => 'GET',
106 description => "Read storage configuration.",
5f642f73
DM
107 permissions => {
108 check => ['perm', '/storage/{storage}', ['Datastore.Allocate']],
109 },
b6cf0a66
DM
110 parameters => {
111 additionalProperties => 0,
112 properties => {
113 storage => get_standard_option('pve-storage-id'),
114 },
115 },
116 returns => {},
117 code => sub {
118 my ($param) = @_;
119
83d7192f 120 my $cfg = PVE::Storage::config();
b6cf0a66
DM
121
122 return &$api_storage_config($cfg, $param->{storage});
123 }});
124
125__PACKAGE__->register_method ({
126 name => 'create',
127 protected => 1,
128 path => '',
129 method => 'POST',
130 description => "Create a new storage.",
5f642f73
DM
131 permissions => {
132 check => ['perm', '/storage', ['Datastore.Allocate']],
133 },
1dc01b9f 134 parameters => PVE::Storage::Plugin->createSchema(),
b6cf0a66
DM
135 returns => { type => 'null' },
136 code => sub {
137 my ($param) = @_;
138
1dc01b9f
DM
139 my $type = extract_param($param, 'type');
140 my $storeid = extract_param($param, 'storage');
b6cf0a66
DM
141
142 if ($param->{portal}) {
143 $param->{portal} = PVE::Storage::resolv_portal($param->{portal});
144 }
145
1dc01b9f
DM
146 my $plugin = PVE::Storage::Plugin->lookup($type);
147 my $opts = $plugin->check_config($storeid, $param, 1, 1);
b6cf0a66
DM
148
149 PVE::Storage::lock_storage_config(
150 sub {
151
83d7192f 152 my $cfg = PVE::Storage::config();
b6cf0a66 153
1dc01b9f 154 if (my $scfg = PVE::Storage::storage_config($cfg, $storeid, 1)) {
b6cf0a66
DM
155 die "storage ID '$storeid' already defined\n";
156 }
157
158 $cfg->{ids}->{$storeid} = $opts;
159
160 if ($type eq 'lvm' && $opts->{base}) {
161
1dc01b9f 162 my ($baseid, $volname) = PVE::Storage::parse_volume_id($opts->{base});
b6cf0a66
DM
163
164 my $basecfg = PVE::Storage::storage_config ($cfg, $baseid, 1);
165 die "base storage ID '$baseid' does not exist\n" if !$basecfg;
166
167 # we only support iscsi for now
168 if (!($basecfg->{type} eq 'iscsi')) {
169 die "unsupported base type '$basecfg->{type}'";
170 }
171
1dc01b9f 172 my $path = PVE::Storage::path($cfg, $opts->{base});
b6cf0a66
DM
173
174 PVE::Storage::activate_storage($cfg, $baseid);
175
1dc01b9f 176 PVE::Storage::LVMPlugin::lvm_create_volume_group($path, $opts->{vgname}, $opts->{shared});
5a39d0a1
FG
177 } elsif ($type eq 'rbd' && !defined($opts->{monhost})) {
178 my $ceph_admin_keyring = '/etc/pve/priv/ceph.client.admin.keyring';
179 my $ceph_storage_keyring = "/etc/pve/priv/ceph/${storeid}.keyring";
180
181 die "ceph authx keyring file for storage '$storeid' already exists!\n"
182 if -e $ceph_storage_keyring;
183
184 eval {
8143f490 185 mkdir '/etc/pve/priv/ceph';
5a39d0a1
FG
186 PVE::Tools::file_copy($ceph_admin_keyring, $ceph_storage_keyring);
187 };
188 if (my $err = $@) {
189 unlink $ceph_storage_keyring;
190 die "failed to copy ceph authx keyring for storage '$storeid': $err\n";
191 }
b6cf0a66
DM
192 }
193
194 # try to activate if enabled on local node,
195 # we only do this to detect errors/problems sooner
196 if (PVE::Storage::storage_check_enabled($cfg, $storeid, undef, 1)) {
197 PVE::Storage::activate_storage($cfg, $storeid);
198 }
199
83d7192f 200 PVE::Storage::write_config($cfg);
b6cf0a66
DM
201
202 }, "create storage failed");
203
1dc01b9f 204 return undef;
b6cf0a66
DM
205 }});
206
207__PACKAGE__->register_method ({
208 name => 'update',
209 protected => 1,
210 path => '{storage}',
211 method => 'PUT',
212 description => "Update storage configuration.",
5f642f73
DM
213 permissions => {
214 check => ['perm', '/storage', ['Datastore.Allocate']],
215 },
1dc01b9f 216 parameters => PVE::Storage::Plugin->updateSchema(),
b6cf0a66
DM
217 returns => { type => 'null' },
218 code => sub {
219 my ($param) = @_;
220
1dc01b9f
DM
221 my $storeid = extract_param($param, 'storage');
222 my $digest = extract_param($param, 'digest');
b6cf0a66
DM
223
224 PVE::Storage::lock_storage_config(
225 sub {
226
83d7192f 227 my $cfg = PVE::Storage::config();
b6cf0a66 228
1dc01b9f 229 PVE::SectionConfig::assert_if_modified($cfg, $digest);
b6cf0a66 230
1dc01b9f 231 my $scfg = PVE::Storage::storage_config($cfg, $storeid);
b6cf0a66 232
1dc01b9f
DM
233 my $plugin = PVE::Storage::Plugin->lookup($scfg->{type});
234 my $opts = $plugin->check_config($storeid, $param, 0, 1);
b6cf0a66
DM
235
236 foreach my $k (%$opts) {
237 $scfg->{$k} = $opts->{$k};
238 }
239
83d7192f 240 PVE::Storage::write_config($cfg);
b6cf0a66
DM
241
242 }, "update storage failed");
243
244 return undef;
245 }});
246
247__PACKAGE__->register_method ({
248 name => 'delete',
249 protected => 1,
250 path => '{storage}', # /storage/config/{storage}
251 method => 'DELETE',
252 description => "Delete storage configuration.",
5f642f73
DM
253 permissions => {
254 check => ['perm', '/storage', ['Datastore.Allocate']],
255 },
b6cf0a66
DM
256 parameters => {
257 additionalProperties => 0,
258 properties => {
f3bd890d
DM
259 storage => get_standard_option('pve-storage-id', {
260 completion => \&PVE::Storage::complete_storage,
261 }),
b6cf0a66
DM
262 },
263 },
264 returns => { type => 'null' },
265 code => sub {
266 my ($param) = @_;
267
1dc01b9f
DM
268 my $storeid = extract_param($param, 'storage');
269
b6cf0a66
DM
270 PVE::Storage::lock_storage_config(
271 sub {
272
83d7192f 273 my $cfg = PVE::Storage::config();
b6cf0a66 274
5a39d0a1 275 my $scfg = PVE::Storage::storage_config($cfg, $storeid);
402df80b 276
b6cf0a66 277 die "can't remove storage - storage is used as base of another storage\n"
1dc01b9f 278 if PVE::Storage::storage_is_used($cfg, $storeid);
b6cf0a66 279
5a39d0a1
FG
280 if ($scfg->{type} eq 'rbd' && !defined($scfg->{monhost})) {
281 my $ceph_storage_keyring = "/etc/pve/priv/ceph/${storeid}.keyring";
282 if (-f $ceph_storage_keyring) {
283 unlink($ceph_storage_keyring) or warn "removing keyring of storage failed: $!\n";
284 }
285 }
286
1dc01b9f 287 delete $cfg->{ids}->{$storeid};
b6cf0a66 288
83d7192f 289 PVE::Storage::write_config($cfg);
b6cf0a66
DM
290
291 }, "delete storage failed");
2a2cf20a
AG
292
293 PVE::AccessControl::remove_storage_access($storeid);
294
b6cf0a66
DM
295 return undef;
296 }});
297
2981;