]>
git.proxmox.com Git - pve-storage.git/blob - PVE/API2/Disks/LVMThin.pm
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);
111 PVE
::Storage
::assert_sid_unused
($name) if $param->{add_storage
};
114 PVE
::Diskmanage
::locked_disk_action
(sub {
115 PVE
::Diskmanage
::assert_disk_unused
($dev);
117 die "volume group with name '${name}' already exists on node '${node}'\n"
118 if PVE
::Storage
::LVMPlugin
::lvm_vgs
()->{$name};
120 if (PVE
::Diskmanage
::is_partition
($dev)) {
121 eval { PVE
::Diskmanage
::change_parttype
($dev, '8E00'); };
125 PVE
::Storage
::LVMPlugin
::lvm_create_volume_group
($dev, $name);
126 my $pv = PVE
::Storage
::LVMPlugin
::lvm_pv_info
($dev);
127 # keep some free space just in case
128 my $datasize = $pv->{size
} - 128*1024;
129 # default to 1% for metadata
130 my $metadatasize = $datasize/100;
131 # but at least 1G, as recommended in lvmthin man
132 $metadatasize = 1024*1024 if $metadatasize < 1024*1024;
133 # but at most 16G, which is the current lvm max
134 $metadatasize = 16*1024*1024 if $metadatasize > 16*1024*1024;
135 # shrink data by needed amount for metadata
136 $datasize -= 2*$metadatasize;
140 '--type', 'thin-pool',
142 '--poolmetadatasize', "${metadatasize}K",
147 PVE
::Diskmanage
::udevadm_trigger
($dev);
149 if ($param->{add_storage
}) {
150 my $storage_params = {
155 content
=> 'rootdir,images',
159 PVE
::API2
::Storage
::Config-
>create($storage_params);
164 return $rpcenv->fork_worker('lvmthincreate', $name, $user, $worker);
167 __PACKAGE__-
>register_method ({
174 check
=> ['perm', '/', ['Sys.Modify', 'Datastore.Allocate']],
176 description
=> "Remove an LVM thin pool.",
178 additionalProperties
=> 0,
180 node
=> get_standard_option
('pve-node'),
181 name
=> get_standard_option
('pve-storage-id'),
182 'volume-group' => get_standard_option
('pve-storage-id'),
183 'cleanup-config' => {
184 description
=> "Marks associated storage(s) as not available on this node anymore ".
185 "or removes them from the configuration (if configured for this node only).",
191 description
=> "Also wipe disks so they can be repurposed afterwards.",
198 returns
=> { type
=> 'string' },
202 my $rpcenv = PVE
::RPCEnvironment
::get
();
203 my $user = $rpcenv->get_user();
205 my $vg = $param->{'volume-group'};
206 my $lv = $param->{name
};
207 my $node = $param->{node
};
210 PVE
::Diskmanage
::locked_disk_action
(sub {
211 my $thinpools = PVE
::Storage
::LvmThinPlugin
::list_thinpools
();
213 die "no such thin pool ${vg}/${lv}\n"
214 if !grep { $_->{lv
} eq $lv && $_->{vg
} eq $vg } $thinpools->@*;
216 run_command
(['lvremove', '-y', "${vg}/${lv}"]);
219 if ($param->{'cleanup-config'}) {
222 return $scfg->{type
} eq 'lvmthin'
223 && $scfg->{vgname
} eq $vg
224 && $scfg->{thinpool
} eq $lv;
226 eval { PVE
::API2
::Storage
::Config-
>cleanup_storages_for_node($match, $node); };
227 warn $config_err = $@ if $@;
230 if ($param->{'cleanup-disks'}) {
231 my $vgs = PVE
::Storage
::LVMPlugin
::lvm_vgs
(1);
233 die "no such volume group '$vg'\n" if !$vgs->{$vg};
234 die "volume group '$vg' still in use\n" if $vgs->{$vg}->{lvcount
} > 0;
238 for my $pv ($vgs->{$vg}->{pvs
}->@*) {
239 my $dev = PVE
::Diskmanage
::verify_blockdev_path
($pv->{name
});
240 PVE
::Diskmanage
::wipe_blockdev
($dev);
241 push $wiped->@*, $dev;
245 PVE
::Diskmanage
::udevadm_trigger
($wiped->@*);
246 die "cleanup failed - $err" if $err;
249 die "config cleanup failed - $config_err" if $config_err;
253 return $rpcenv->fork_worker('lvmthinremove', "${vg}-${lv}", $user, $worker);