]>
git.proxmox.com Git - pve-storage.git/blob - PVE/API2/Disks/Directory.pm
1 package PVE
::API2
::Disks
::Directory
;
7 use PVE
::JSONSchema
qw(get_standard_option);
8 use PVE
::API2
::Storage
::Config
;
9 use PVE
::Tools
qw(run_command trim file_set_contents file_get_contents dir_glob_foreach lock_file);
11 use PVE
::RPCEnvironment
;
14 use base
qw(PVE::RESTHandler);
16 my $SGDISK = '/sbin/sgdisk';
17 my $MKFS = '/sbin/mkfs';
18 my $BLKID = '/sbin/blkid';
23 my $content = file_get_contents
($filename);
24 my @lines = split /\n/, $content;
29 foreach my $line (@lines) {
31 if ($line =~ m/^\[([^\]]+)\]/) {
33 if (!defined($result->{$section})) {
34 $result->{$section} = {};
36 } elsif ($line =~ m/^(.*?)=(.*)$/) {
37 my ($key, $val) = ($1, $2);
39 warn "key value pair found without section, skipping\n";
43 if ($result->{$section}->{$key}) {
44 # make duplicate properties to arrays to keep the order
45 my $prop = $result->{$section}->{$key};
46 if (ref($prop) eq 'ARRAY') {
49 $result->{$section}->{$key} = [$prop, $val];
52 $result->{$section}->{$key} = $val;
55 # ignore everything else
62 my ($ini, $filename) = @_;
66 foreach my $sname (sort keys %$ini) {
67 my $section = $ini->{$sname};
69 $content .= "[$sname]\n";
71 foreach my $pname (sort keys %$section) {
72 my $prop = $section->{$pname};
75 $content .= "$pname=$prop\n";
76 } elsif (ref($prop) eq 'ARRAY') {
77 foreach my $val (@$prop) {
78 $content .= "$pname=$val\n";
81 die "invalid property '$pname'\n";
87 file_set_contents
($filename, $content);
90 __PACKAGE__-
>register_method ({
97 check
=> ['perm', '/', ['Sys.Audit', 'Datastore.Audit'], any
=> 1],
99 description
=> "PVE Managed Directory storages.",
101 additionalProperties
=> 0,
103 node
=> get_standard_option
('pve-node'),
113 description
=> 'The path of the mount unit.',
117 description
=> 'The mount path.',
121 description
=> 'The mounted device.',
125 description
=> 'The filesystem type.',
129 description
=> 'The mount options.',
139 dir_glob_foreach
('/etc/systemd/system', '^mnt-pve-(.+)\.mount$', sub {
140 my ($filename, $storid) = @_;
142 my $unitfile = "/etc/systemd/system/$filename";
143 my $unit = $read_ini->($unitfile);
146 unitfile
=> $unitfile,
147 path
=> "/mnt/pve/$storid",
148 device
=> $unit->{'Mount'}->{'What'},
149 type
=> $unit->{'Mount'}->{'Type'},
150 options
=> $unit->{'Mount'}->{'Options'},
157 __PACKAGE__-
>register_method ({
164 check
=> ['perm', '/', ['Sys.Modify', 'Datastore.Allocate']],
166 description
=> "Create a Filesystem on an unused disk. Will be mounted under '/mnt/pve/NAME'.",
168 additionalProperties
=> 0,
170 node
=> get_standard_option
('pve-node'),
171 name
=> get_standard_option
('pve-storage-id'),
174 description
=> 'The block device you want to create the filesystem on.',
177 description
=> "Configure storage using the directory.",
183 description
=> "The desired filesystem.",
185 enum
=> ['ext4', 'xfs'],
191 returns
=> { type
=> 'string' },
195 my $rpcenv = PVE
::RPCEnvironment
::get
();
196 my $user = $rpcenv->get_user();
198 my $name = $param->{name
};
199 my $dev = $param->{device
};
200 my $node = $param->{node
};
201 my $type = $param->{filesystem
} // 'ext4';
203 $dev = PVE
::Diskmanage
::verify_blockdev_path
($dev);
204 PVE
::Diskmanage
::check_unused
($dev);
205 PVE
::Storage
::check_available
($name) if $param->{add_storage
};
208 my $path = "/mnt/pve/$name";
209 my $mountunitname = "mnt-pve-$name.mount";
210 my $mountunitpath = "/etc/systemd/system/$mountunitname";
212 PVE
::Diskmanage
::locked_disk_action
(sub {
214 my $cmd = [$SGDISK, '-n1', '-t1:8300', $dev];
215 print "# ", join(' ', @$cmd), "\n";
218 my ($devname) = $dev =~ m
|^/dev/(.*)$|;
220 dir_glob_foreach
("/sys/block/$devname", qr
/\Q
$devname\E.+/, sub {
221 my ($partition) = @_;
226 $cmd = [$MKFS, '-t', $type, $part];
227 print "# ", join(' ', @$cmd), "\n";
230 # create systemd mount unit and enable & start it
233 'Description' => "Mount storage '$name' under /mnt/pve",
236 'WantedBy' => 'multi-user.target',
243 $cmd = [$BLKID, $part, '-o', 'export'];
244 print "# ", join(' ', @$cmd), "\n";
245 run_command
($cmd, outfunc
=> sub {
248 if ($line =~ m/^UUID=(.*)$/) {
250 $uuid_path = "/dev/disk/by-uuid/$uuid";
254 die "could not get UUID of device '$part'\n" if !$uuid;
257 'What' => $uuid_path,
260 'Options' => 'defaults',
263 $write_ini->($ini, $mountunitpath);
265 run_command
(['systemctl', 'daemon-reload']);
266 run_command
(['systemctl', 'enable', $mountunitname]);
267 run_command
(['systemctl', 'start', $mountunitname]);
269 if ($param->{add_storage
}) {
270 my $storage_params = {
273 content
=> 'rootdir,images,iso,backup,vztmpl',
279 PVE
::API2
::Storage
::Config-
>create($storage_params);
284 return $rpcenv->fork_worker('dircreate', $name, $user, $worker);