]>
git.proxmox.com Git - pve-storage.git/blob - PVE/API2/Storage/Config.pm
a7d9bf6040cbcb8b79e094dea1762f114b51e5f6
1 package PVE
::API2
::Storage
::Config
;
7 use PVE
::Tools
qw(extract_param);
8 use PVE
::Cluster
qw(cfs_read_file cfs_write_file);
10 use PVE
::Storage
::Plugin
;
11 use PVE
::Storage
::LVMPlugin
;
12 use HTTP
::Status
qw(:constants);
13 use Storable
qw(dclone);
14 use PVE
::JSONSchema
qw(get_standard_option);
15 use PVE
::RPCEnvironment
;
19 use base
qw(PVE::RESTHandler);
21 my @ctypes = qw(images vztmpl iso backup);
23 my $storage_type_enum = PVE
::Storage
::Plugin-
>lookup_types();
25 my $api_storage_config = sub {
26 my ($cfg, $storeid) = @_;
28 my $scfg = dclone
(PVE
::Storage
::storage_config
($cfg, $storeid));
29 $scfg->{storage
} = $storeid;
30 $scfg->{digest
} = $cfg->{digest
};
31 $scfg->{content
} = PVE
::Storage
::Plugin-
>encode_value($scfg->{type
}, 'content', $scfg->{content
});
34 $scfg->{nodes
} = PVE
::Storage
::Plugin-
>encode_value($scfg->{type
}, 'nodes', $scfg->{nodes
});
40 my $cifs_cred_file_name = sub {
43 return "/etc/pve/priv/${storeid}.cred";
46 my $set_cifs_credentials = sub {
47 my ($password, $storeid) = @_;
49 my $cred_file = $cifs_cred_file_name->($storeid);
51 PVE
::Tools
::file_set_contents
($cred_file, "password=$password\n");
56 __PACKAGE__-
>register_method ({
60 description
=> "Storage index.",
62 description
=> "Only list entries where you have 'Datastore.Audit' or 'Datastore.AllocateSpace' permissions on '/storage/<storage>'",
66 additionalProperties
=> 0,
69 description
=> "Only list storage of specific type",
71 enum
=> $storage_type_enum,
80 properties
=> { storage
=> { type
=> 'string'} },
82 links
=> [ { rel
=> 'child', href
=> "{storage}" } ],
87 my $rpcenv = PVE
::RPCEnvironment
::get
();
88 my $authuser = $rpcenv->get_user();
90 my $cfg = PVE
::Storage
::config
();
92 my @sids = PVE
::Storage
::storage_ids
($cfg);
95 foreach my $storeid (@sids) {
96 my $privs = [ 'Datastore.Audit', 'Datastore.AllocateSpace' ];
97 next if !$rpcenv->check_any($authuser, "/storage/$storeid", $privs, 1);
99 my $scfg = &$api_storage_config($cfg, $storeid);
100 next if $param->{type
} && $param->{type
} ne $scfg->{type
};
107 __PACKAGE__-
>register_method ({
111 description
=> "Read storage configuration.",
113 check
=> ['perm', '/storage/{storage}', ['Datastore.Allocate']],
116 additionalProperties
=> 0,
118 storage
=> get_standard_option
('pve-storage-id'),
125 my $cfg = PVE
::Storage
::config
();
127 return &$api_storage_config($cfg, $param->{storage
});
130 __PACKAGE__-
>register_method ({
135 description
=> "Create a new storage.",
137 check
=> ['perm', '/storage', ['Datastore.Allocate']],
139 parameters
=> PVE
::Storage
::Plugin-
>createSchema(),
140 returns
=> { type
=> 'null' },
144 my $type = extract_param
($param, 'type');
145 my $storeid = extract_param
($param, 'storage');
147 # revent an empty nodelist.
148 # fix me in section config create never need an empty entity.
149 delete $param->{nodes
} if !$param->{nodes
};
151 my $password = extract_param
($param, 'password')
152 if $type eq 'cifs' && $param->{username
};
154 if ($param->{portal
}) {
155 $param->{portal
} = PVE
::Storage
::resolv_portal
($param->{portal
});
158 my $plugin = PVE
::Storage
::Plugin-
>lookup($type);
159 my $opts = $plugin->check_config($storeid, $param, 1, 1);
161 PVE
::Storage
::lock_storage_config
(
164 my $cfg = PVE
::Storage
::config
();
166 if (my $scfg = PVE
::Storage
::storage_config
($cfg, $storeid, 1)) {
167 die "storage ID '$storeid' already defined\n";
170 $cfg->{ids
}->{$storeid} = $opts;
172 if ($type eq 'lvm' && $opts->{base
}) {
174 my ($baseid, $volname) = PVE
::Storage
::parse_volume_id
($opts->{base
});
176 my $basecfg = PVE
::Storage
::storage_config
($cfg, $baseid, 1);
177 die "base storage ID '$baseid' does not exist\n" if !$basecfg;
179 # we only support iscsi for now
180 if (!($basecfg->{type
} eq 'iscsi')) {
181 die "unsupported base type '$basecfg->{type}'";
184 my $path = PVE
::Storage
::path
($cfg, $opts->{base
});
186 PVE
::Storage
::activate_storage
($cfg, $baseid);
188 PVE
::Storage
::LVMPlugin
::lvm_create_volume_group
($path, $opts->{vgname
}, $opts->{shared
});
189 } elsif ($type eq 'rbd' && !defined($opts->{monhost
})) {
190 my $ceph_admin_keyring = '/etc/pve/priv/ceph.client.admin.keyring';
191 my $ceph_storage_keyring = "/etc/pve/priv/ceph/${storeid}.keyring";
193 die "ceph authx keyring file for storage '$storeid' already exists!\n"
194 if -e
$ceph_storage_keyring;
197 mkdir '/etc/pve/priv/ceph';
198 PVE
::Tools
::file_copy
($ceph_admin_keyring, $ceph_storage_keyring);
201 unlink $ceph_storage_keyring;
202 die "failed to copy ceph authx keyring for storage '$storeid': $err\n";
205 # create a password file in /etc/pve/priv,
206 # this file is used as a cert_file at mount time.
207 my $cred_file = &$set_cifs_credentials($password, $storeid)
208 if defined($password);
211 # try to activate if enabled on local node,
212 # we only do this to detect errors/problems sooner
213 if (PVE
::Storage
::storage_check_enabled
($cfg, $storeid, undef, 1)) {
214 PVE
::Storage
::activate_storage
($cfg, $storeid);
218 unlink $cred_file if defined($cred_file);
222 PVE
::Storage
::write_config
($cfg);
224 }, "create storage failed");
229 __PACKAGE__-
>register_method ({
234 description
=> "Update storage configuration.",
236 check
=> ['perm', '/storage', ['Datastore.Allocate']],
238 parameters
=> PVE
::Storage
::Plugin-
>updateSchema(),
239 returns
=> { type
=> 'null' },
243 my $storeid = extract_param
($param, 'storage');
244 my $digest = extract_param
($param, 'digest');
246 PVE
::Storage
::lock_storage_config
(
249 my $cfg = PVE
::Storage
::config
();
251 PVE
::SectionConfig
::assert_if_modified
($cfg, $digest);
253 my $scfg = PVE
::Storage
::storage_config
($cfg, $storeid);
255 my $plugin = PVE
::Storage
::Plugin-
>lookup($scfg->{type
});
256 my $opts = $plugin->check_config($storeid, $param, 0, 1);
258 foreach my $k (%$opts) {
259 $scfg->{$k} = $opts->{$k};
262 PVE
::Storage
::write_config
($cfg);
264 }, "update storage failed");
269 __PACKAGE__-
>register_method ({
272 path
=> '{storage}', # /storage/config/{storage}
274 description
=> "Delete storage configuration.",
276 check
=> ['perm', '/storage', ['Datastore.Allocate']],
279 additionalProperties
=> 0,
281 storage
=> get_standard_option
('pve-storage-id', {
282 completion
=> \
&PVE
::Storage
::complete_storage
,
286 returns
=> { type
=> 'null' },
290 my $storeid = extract_param
($param, 'storage');
292 PVE
::Storage
::lock_storage_config
(
295 my $cfg = PVE
::Storage
::config
();
297 my $scfg = PVE
::Storage
::storage_config
($cfg, $storeid);
299 die "can't remove storage - storage is used as base of another storage\n"
300 if PVE
::Storage
::storage_is_used
($cfg, $storeid);
302 if ($scfg->{type
} eq 'cifs') {
303 my $cred_file = $cifs_cred_file_name->($storeid);
305 unlink($cred_file) or warn "removing cifs credientials '$cred_file' failed: $!\n";
307 } elsif ($scfg->{type
} eq 'rbd' && !defined($scfg->{monhost
})) {
308 my $ceph_storage_keyring = "/etc/pve/priv/ceph/${storeid}.keyring";
309 if (-f
$ceph_storage_keyring) {
310 unlink($ceph_storage_keyring) or warn "removing keyring of storage failed: $!\n";
314 delete $cfg->{ids
}->{$storeid};
316 PVE
::Storage
::write_config
($cfg);
318 }, "delete storage failed");
320 PVE
::AccessControl
::remove_storage_access
($storeid);