]>
git.proxmox.com Git - pve-storage.git/blob - PVE/API2/Disks/LVMThin.pm
038310a4864c6e82234ee7dc75fbaa2a7ce6b1de
1 package PVE
::API2
::Disks
::LVMThin
;
6 use PVE
::Storage
::LvmThinPlugin
;
8 use PVE
::JSONSchema
qw(get_standard_option);
9 use PVE
::API2
::Storage
::Config
;
11 use PVE
::Tools
qw(run_command lock_file);
13 use PVE
::RPCEnvironment
;
16 use base
qw(PVE::RESTHandler);
18 __PACKAGE__-
>register_method ({
25 check
=> ['perm', '/', ['Sys.Audit', 'Datastore.Audit'], any
=> 1],
27 description
=> "List LVM thinpools",
29 additionalProperties
=> 0,
31 node
=> get_standard_option
('pve-node'),
41 description
=> 'The name of the thinpool.',
45 description
=> 'The associated volume group.',
49 description
=> 'The size of the thinpool in bytes.',
53 description
=> 'The used bytes of the thinpool.',
57 description
=> 'The size of the metadata lv in bytes.',
61 description
=> 'The used bytes of the metadata lv.',
68 return PVE
::Storage
::LvmThinPlugin
::list_thinpools
(undef);
71 __PACKAGE__-
>register_method ({
78 check
=> ['perm', '/', ['Sys.Modify', 'Datastore.Allocate']],
80 description
=> "Create an LVM thinpool",
82 additionalProperties
=> 0,
84 node
=> get_standard_option
('pve-node'),
85 name
=> get_standard_option
('pve-storage-id'),
88 description
=> 'The block device you want to create the thinpool on.',
91 description
=> "Configure storage using the thinpool.",
98 returns
=> { type
=> 'string' },
102 my $rpcenv = PVE
::RPCEnvironment
::get
();
103 my $user = $rpcenv->get_user();
105 my $name = $param->{name
};
106 my $dev = $param->{device
};
107 my $node = $param->{node
};
109 $dev = PVE
::Diskmanage
::verify_blockdev_path
($dev);
110 PVE
::Diskmanage
::assert_disk_unused
($dev);
112 my $storage_params = {
117 content
=> 'rootdir,images',
120 my $verify_params = [qw(vgname thinpool)];
122 if ($param->{add_storage
}) {
123 PVE
::API2
::Storage
::Config-
>create_or_update(
133 PVE
::Diskmanage
::locked_disk_action
(sub {
134 PVE
::Diskmanage
::assert_disk_unused
($dev);
136 die "volume group with name '${name}' already exists on node '${node}'\n"
137 if PVE
::Storage
::LVMPlugin
::lvm_vgs
()->{$name};
139 if (PVE
::Diskmanage
::is_partition
($dev)) {
140 eval { PVE
::Diskmanage
::change_parttype
($dev, '8E00'); };
144 PVE
::Storage
::LVMPlugin
::lvm_create_volume_group
($dev, $name);
145 my $pv = PVE
::Storage
::LVMPlugin
::lvm_pv_info
($dev);
146 # keep some free space just in case
147 my $datasize = $pv->{size
} - 128*1024;
148 # default to 1% for metadata
149 my $metadatasize = $datasize/100;
150 # but at least 1G, as recommended in lvmthin man
151 $metadatasize = 1024*1024 if $metadatasize < 1024*1024;
152 # but at most 16G, which is the current lvm max
153 $metadatasize = 16*1024*1024 if $metadatasize > 16*1024*1024;
154 # shrink data by needed amount for metadata
155 $datasize -= 2*$metadatasize;
159 '--type', 'thin-pool',
161 '--poolmetadatasize', "${metadatasize}K",
166 PVE
::Diskmanage
::udevadm_trigger
($dev);
168 if ($param->{add_storage
}) {
169 PVE
::API2
::Storage
::Config-
>create_or_update(
179 return $rpcenv->fork_worker('lvmthincreate', $name, $user, $worker);
182 __PACKAGE__-
>register_method ({
189 check
=> ['perm', '/', ['Sys.Modify', 'Datastore.Allocate']],
191 description
=> "Remove an LVM thin pool.",
193 additionalProperties
=> 0,
195 node
=> get_standard_option
('pve-node'),
196 name
=> get_standard_option
('pve-storage-id'),
197 'volume-group' => get_standard_option
('pve-storage-id'),
198 'cleanup-config' => {
199 description
=> "Marks associated storage(s) as not available on this node anymore ".
200 "or removes them from the configuration (if configured for this node only).",
206 description
=> "Also wipe disks so they can be repurposed afterwards.",
213 returns
=> { type
=> 'string' },
217 my $rpcenv = PVE
::RPCEnvironment
::get
();
218 my $user = $rpcenv->get_user();
220 my $vg = $param->{'volume-group'};
221 my $lv = $param->{name
};
222 my $node = $param->{node
};
225 PVE
::Diskmanage
::locked_disk_action
(sub {
226 my $thinpools = PVE
::Storage
::LvmThinPlugin
::list_thinpools
();
228 die "no such thin pool ${vg}/${lv}\n"
229 if !grep { $_->{lv
} eq $lv && $_->{vg
} eq $vg } $thinpools->@*;
231 run_command
(['lvremove', '-y', "${vg}/${lv}"]);
234 if ($param->{'cleanup-config'}) {
237 return $scfg->{type
} eq 'lvmthin'
238 && $scfg->{vgname
} eq $vg
239 && $scfg->{thinpool
} eq $lv;
241 eval { PVE
::API2
::Storage
::Config-
>cleanup_storages_for_node($match, $node); };
242 warn $config_err = $@ if $@;
245 if ($param->{'cleanup-disks'}) {
246 my $vgs = PVE
::Storage
::LVMPlugin
::lvm_vgs
(1);
248 die "no such volume group '$vg'\n" if !$vgs->{$vg};
249 die "volume group '$vg' still in use\n" if $vgs->{$vg}->{lvcount
} > 0;
253 for my $pv ($vgs->{$vg}->{pvs
}->@*) {
254 my $dev = PVE
::Diskmanage
::verify_blockdev_path
($pv->{name
});
255 PVE
::Diskmanage
::wipe_blockdev
($dev);
256 push $wiped->@*, $dev;
260 PVE
::Diskmanage
::udevadm_trigger
($wiped->@*);
261 die "cleanup failed - $err" if $err;
264 die "config cleanup failed - $config_err" if $config_err;
268 return $rpcenv->fork_worker('lvmthinremove', "${vg}-${lv}", $user, $worker);