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