]>
Commit | Line | Data |
---|---|---|
6fb08cb9 | 1 | package PVE::Ceph::Tools; |
a34866f0 DM |
2 | |
3 | use strict; | |
4 | use warnings; | |
f8346b52 | 5 | |
a34866f0 | 6 | use File::Path; |
b436dca8 | 7 | use File::Basename; |
f8346b52 | 8 | use IO::File; |
a34866f0 | 9 | |
f8346b52 | 10 | use PVE::Tools qw(run_command dir_glob_foreach); |
f96d7012 | 11 | use PVE::RADOS; |
a34866f0 DM |
12 | |
13 | my $ccname = 'ceph'; # ceph cluster name | |
14 | my $ceph_cfgdir = "/etc/ceph"; | |
15 | my $pve_ceph_cfgpath = "/etc/pve/$ccname.conf"; | |
16 | my $ceph_cfgpath = "$ceph_cfgdir/$ccname.conf"; | |
17 | ||
18 | my $pve_mon_key_path = "/etc/pve/priv/$ccname.mon.keyring"; | |
19 | my $pve_ckeyring_path = "/etc/pve/priv/$ccname.client.admin.keyring"; | |
20 | my $ceph_bootstrap_osd_keyring = "/var/lib/ceph/bootstrap-osd/$ccname.keyring"; | |
21 | my $ceph_bootstrap_mds_keyring = "/var/lib/ceph/bootstrap-mds/$ccname.keyring"; | |
b82649cc | 22 | my $ceph_mds_data_dir = '/var/lib/ceph/mds'; |
a34866f0 | 23 | |
c64c04dd AA |
24 | my $ceph_service = { |
25 | ceph_bin => "/usr/bin/ceph", | |
26 | ceph_mon => "/usr/bin/ceph-mon", | |
27 | ceph_mgr => "/usr/bin/ceph-mgr", | |
b82649cc TL |
28 | ceph_osd => "/usr/bin/ceph-osd", |
29 | ceph_mds => "/usr/bin/ceph-mds", | |
c64c04dd | 30 | }; |
a34866f0 DM |
31 | |
32 | my $config_hash = { | |
33 | ccname => $ccname, | |
34 | pve_ceph_cfgpath => $pve_ceph_cfgpath, | |
35 | pve_mon_key_path => $pve_mon_key_path, | |
36 | pve_ckeyring_path => $pve_ckeyring_path, | |
37 | ceph_bootstrap_osd_keyring => $ceph_bootstrap_osd_keyring, | |
38 | ceph_bootstrap_mds_keyring => $ceph_bootstrap_mds_keyring, | |
b82649cc | 39 | ceph_mds_data_dir => $ceph_mds_data_dir, |
7d4fc5ef | 40 | long_rados_timeout => 60, |
a34866f0 DM |
41 | }; |
42 | ||
c64c04dd AA |
43 | sub get_local_version { |
44 | my ($noerr) = @_; | |
45 | ||
6fb08cb9 | 46 | if (check_ceph_installed('ceph_bin', $noerr)) { |
c64c04dd AA |
47 | my $ceph_version; |
48 | run_command([$ceph_service->{ceph_bin}, '--version'], | |
49 | noerr => $noerr, | |
50 | outfunc => sub { $ceph_version = shift; }); | |
51 | if ($ceph_version && $ceph_version =~ /^ceph.*\s((\d+)\.(\d+)\.(\d+))/) { | |
52 | # return (version, major, minor, patch) : major; | |
53 | return wantarray ? ($1, $2, $3, $4) : $2; | |
54 | } | |
55 | } | |
56 | ||
57 | return undef; | |
58 | } | |
59 | ||
a34866f0 DM |
60 | sub get_config { |
61 | my $key = shift; | |
62 | ||
63 | my $value = $config_hash->{$key}; | |
64 | ||
6f8bf83d | 65 | die "no such ceph config '$key'" if !$value; |
a34866f0 DM |
66 | |
67 | return $value; | |
68 | } | |
69 | ||
a34866f0 DM |
70 | sub purge_all_ceph_files { |
71 | # fixme: this is very dangerous - should we really support this function? | |
72 | ||
73 | unlink $ceph_cfgpath; | |
74 | ||
75 | unlink $pve_ceph_cfgpath; | |
76 | unlink $pve_ckeyring_path; | |
77 | unlink $pve_mon_key_path; | |
78 | ||
79 | unlink $ceph_bootstrap_osd_keyring; | |
80 | unlink $ceph_bootstrap_mds_keyring; | |
81 | ||
82 | system("rm -rf /var/lib/ceph/mon/ceph-*"); | |
83 | ||
84 | # remove osd? | |
85 | } | |
86 | ||
87 | sub check_ceph_installed { | |
c64c04dd AA |
88 | my ($service, $noerr) = @_; |
89 | ||
90 | $service = 'ceph_bin' if !defined($service); | |
a34866f0 | 91 | |
c64c04dd AA |
92 | if (! -x $ceph_service->{$service}) { |
93 | die "binary not installed: $ceph_service->{$service}\n" if !$noerr; | |
a34866f0 DM |
94 | return undef; |
95 | } | |
96 | ||
97 | return 1; | |
98 | } | |
99 | ||
100 | sub check_ceph_inited { | |
101 | my ($noerr) = @_; | |
102 | ||
315304f3 | 103 | return undef if !check_ceph_installed('ceph_mon', $noerr); |
6f8bf83d | 104 | |
a34866f0 DM |
105 | if (! -f $pve_ceph_cfgpath) { |
106 | die "pveceph configuration not initialized\n" if !$noerr; | |
107 | return undef; | |
108 | } | |
109 | ||
110 | return 1; | |
111 | } | |
112 | ||
113 | sub check_ceph_enabled { | |
114 | my ($noerr) = @_; | |
115 | ||
116 | return undef if !check_ceph_inited($noerr); | |
117 | ||
118 | if (! -f $ceph_cfgpath) { | |
119 | die "pveceph configuration not enabled\n" if !$noerr; | |
120 | return undef; | |
121 | } | |
122 | ||
123 | return 1; | |
124 | } | |
125 | ||
f96d7012 TL |
126 | sub create_pool { |
127 | my ($pool, $param, $rados) = @_; | |
128 | ||
129 | if (!defined($rados)) { | |
130 | $rados = PVE::RADOS->new(); | |
131 | } | |
132 | ||
6ad70a2b | 133 | my $pg_num = $param->{pg_num} || 128; |
f96d7012 TL |
134 | my $size = $param->{size} || 3; |
135 | my $min_size = $param->{min_size} || 2; | |
136 | my $application = $param->{application} // 'rbd'; | |
137 | ||
138 | $rados->mon_command({ | |
139 | prefix => "osd pool create", | |
140 | pool => $pool, | |
141 | pg_num => int($pg_num), | |
142 | format => 'plain', | |
143 | }); | |
144 | ||
145 | $rados->mon_command({ | |
146 | prefix => "osd pool set", | |
147 | pool => $pool, | |
148 | var => 'min_size', | |
507b7cfe | 149 | val => "$min_size", |
f96d7012 TL |
150 | format => 'plain', |
151 | }); | |
152 | ||
153 | $rados->mon_command({ | |
154 | prefix => "osd pool set", | |
155 | pool => $pool, | |
156 | var => 'size', | |
507b7cfe | 157 | val => "$size", |
f96d7012 TL |
158 | format => 'plain', |
159 | }); | |
160 | ||
161 | if (defined($param->{crush_rule})) { | |
162 | $rados->mon_command({ | |
163 | prefix => "osd pool set", | |
164 | pool => $pool, | |
165 | var => 'crush_rule', | |
166 | val => $param->{crush_rule}, | |
167 | format => 'plain', | |
168 | }); | |
169 | } | |
170 | ||
171 | $rados->mon_command({ | |
172 | prefix => "osd pool application enable", | |
173 | pool => $pool, | |
174 | app => $application, | |
175 | }); | |
176 | ||
177 | } | |
178 | ||
7e1a9d25 TL |
179 | sub ls_pools { |
180 | my ($pool, $rados) = @_; | |
181 | ||
182 | if (!defined($rados)) { | |
183 | $rados = PVE::RADOS->new(); | |
184 | } | |
185 | ||
186 | my $res = $rados->mon_command({ prefix => "osd lspools" }); | |
187 | ||
188 | return $res; | |
189 | } | |
190 | ||
f96d7012 TL |
191 | sub destroy_pool { |
192 | my ($pool, $rados) = @_; | |
193 | ||
194 | if (!defined($rados)) { | |
195 | $rados = PVE::RADOS->new(); | |
196 | } | |
197 | ||
198 | # fixme: '--yes-i-really-really-mean-it' | |
199 | $rados->mon_command({ | |
200 | prefix => "osd pool delete", | |
201 | pool => $pool, | |
202 | pool2 => $pool, | |
203 | sure => '--yes-i-really-really-mean-it', | |
204 | format => 'plain', | |
205 | }); | |
206 | } | |
207 | ||
a34866f0 DM |
208 | sub setup_pve_symlinks { |
209 | # fail if we find a real file instead of a link | |
210 | if (-f $ceph_cfgpath) { | |
211 | my $lnk = readlink($ceph_cfgpath); | |
212 | die "file '$ceph_cfgpath' already exists\n" | |
213 | if !$lnk || $lnk ne $pve_ceph_cfgpath; | |
214 | } else { | |
215 | symlink($pve_ceph_cfgpath, $ceph_cfgpath) || | |
216 | die "unable to create symlink '$ceph_cfgpath' - $!\n"; | |
217 | } | |
218 | } | |
219 | ||
456a7f4d AA |
220 | # wipe the first 200 MB to clear off leftovers from previous use, otherwise a |
221 | # create OSD fails. | |
1343ae6d | 222 | sub wipe_disks { |
456a7f4d AA |
223 | my (@devs) = @_; |
224 | ||
b436dca8 AA |
225 | my @wipe_cmd = qw(/bin/dd if=/dev/zero bs=1M conv=fdatasync); |
226 | ||
a1a7aa74 | 227 | foreach my $devpath (@devs) { |
b436dca8 AA |
228 | my $devname = basename($devpath); |
229 | my $dev_size = PVE::Tools::file_get_contents("/sys/class/block/$devname/size"); | |
230 | ||
231 | ($dev_size) = $dev_size =~ m|(\d+)|; # untaint $dev_size | |
232 | die "Coulnd't get the size of the device $devname\n" if (!defined($dev_size)); | |
233 | ||
234 | my $size = ($dev_size * 512 / 1024 / 1024); | |
235 | my $count = ($size < 200) ? $size : 200; | |
236 | ||
237 | print "wipe disk/partition: $devpath\n"; | |
238 | eval { run_command([@wipe_cmd, "count=$count", "of=${devpath}"]) }; | |
239 | warn $@ if $@; | |
456a7f4d AA |
240 | } |
241 | }; | |
242 | ||
a34866f0 | 243 | 1; |