]>
Commit | Line | Data |
---|---|---|
a34866f0 DM |
1 | package PVE::CephTools; |
2 | ||
3 | use strict; | |
4 | use warnings; | |
5 | use File::Basename; | |
6 | use File::Path; | |
7 | use POSIX qw (LONG_MAX); | |
8 | use Cwd qw(abs_path); | |
7d4fc5ef | 9 | use IO::Dir; |
a34866f0 | 10 | |
7d4fc5ef | 11 | use PVE::Tools qw(extract_param run_command file_get_contents file_read_firstline dir_glob_regex dir_glob_foreach); |
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"; | |
22 | ||
23 | my $ceph_bin = "/usr/bin/ceph"; | |
24 | ||
25 | my $config_hash = { | |
26 | ccname => $ccname, | |
27 | pve_ceph_cfgpath => $pve_ceph_cfgpath, | |
28 | pve_mon_key_path => $pve_mon_key_path, | |
29 | pve_ckeyring_path => $pve_ckeyring_path, | |
30 | ceph_bootstrap_osd_keyring => $ceph_bootstrap_osd_keyring, | |
31 | ceph_bootstrap_mds_keyring => $ceph_bootstrap_mds_keyring, | |
7d4fc5ef | 32 | long_rados_timeout => 60, |
a34866f0 DM |
33 | }; |
34 | ||
35 | sub get_config { | |
36 | my $key = shift; | |
37 | ||
38 | my $value = $config_hash->{$key}; | |
39 | ||
6f8bf83d | 40 | die "no such ceph config '$key'" if !$value; |
a34866f0 DM |
41 | |
42 | return $value; | |
43 | } | |
44 | ||
a34866f0 DM |
45 | sub purge_all_ceph_files { |
46 | # fixme: this is very dangerous - should we really support this function? | |
47 | ||
48 | unlink $ceph_cfgpath; | |
49 | ||
50 | unlink $pve_ceph_cfgpath; | |
51 | unlink $pve_ckeyring_path; | |
52 | unlink $pve_mon_key_path; | |
53 | ||
54 | unlink $ceph_bootstrap_osd_keyring; | |
55 | unlink $ceph_bootstrap_mds_keyring; | |
56 | ||
57 | system("rm -rf /var/lib/ceph/mon/ceph-*"); | |
58 | ||
59 | # remove osd? | |
60 | } | |
61 | ||
62 | sub check_ceph_installed { | |
63 | my ($noerr) = @_; | |
64 | ||
65 | if (! -x $ceph_bin) { | |
66 | die "ceph binaries not installed\n" if !$noerr; | |
67 | return undef; | |
68 | } | |
69 | ||
70 | return 1; | |
71 | } | |
72 | ||
73 | sub check_ceph_inited { | |
74 | my ($noerr) = @_; | |
75 | ||
76 | return undef if !check_ceph_installed($noerr); | |
6f8bf83d | 77 | |
a34866f0 DM |
78 | if (! -f $pve_ceph_cfgpath) { |
79 | die "pveceph configuration not initialized\n" if !$noerr; | |
80 | return undef; | |
81 | } | |
82 | ||
83 | return 1; | |
84 | } | |
85 | ||
86 | sub check_ceph_enabled { | |
87 | my ($noerr) = @_; | |
88 | ||
89 | return undef if !check_ceph_inited($noerr); | |
90 | ||
91 | if (! -f $ceph_cfgpath) { | |
92 | die "pveceph configuration not enabled\n" if !$noerr; | |
93 | return undef; | |
94 | } | |
95 | ||
96 | return 1; | |
97 | } | |
98 | ||
99 | sub parse_ceph_config { | |
100 | my ($filename) = @_; | |
101 | ||
102 | $filename = $pve_ceph_cfgpath if !$filename; | |
103 | ||
104 | my $cfg = {}; | |
105 | ||
106 | return $cfg if ! -f $filename; | |
107 | ||
108 | my $fh = IO::File->new($filename, "r") || | |
109 | die "unable to open '$filename' - $!\n"; | |
110 | ||
111 | my $section; | |
112 | ||
113 | while (defined(my $line = <$fh>)) { | |
114 | $line =~ s/[;#].*$//; | |
115 | $line =~ s/^\s+//; | |
116 | $line =~ s/\s+$//; | |
117 | next if !$line; | |
118 | ||
119 | $section = $1 if $line =~ m/^\[(\S+)\]$/; | |
120 | if (!$section) { | |
121 | warn "no section - skip: $line\n"; | |
122 | next; | |
123 | } | |
124 | ||
15a5cdd1 | 125 | if ($line =~ m/^(.*?\S)\s*=\s*(\S.*)$/) { |
a34866f0 DM |
126 | $cfg->{$section}->{$1} = $2; |
127 | } | |
128 | ||
129 | } | |
130 | ||
131 | return $cfg; | |
132 | } | |
133 | ||
134 | sub write_ceph_config { | |
135 | my ($cfg) = @_; | |
136 | ||
137 | my $out = ''; | |
138 | ||
139 | my $cond_write_sec = sub { | |
140 | my $re = shift; | |
141 | ||
142 | foreach my $section (keys %$cfg) { | |
143 | next if $section !~ m/^$re$/; | |
144 | $out .= "[$section]\n"; | |
145 | foreach my $key (sort keys %{$cfg->{$section}}) { | |
146 | $out .= "\t $key = $cfg->{$section}->{$key}\n"; | |
147 | } | |
148 | $out .= "\n"; | |
149 | } | |
150 | }; | |
151 | ||
152 | &$cond_write_sec('global'); | |
19924e77 | 153 | &$cond_write_sec('client'); |
0fe9bdd5 DM |
154 | &$cond_write_sec('mds'); |
155 | &$cond_write_sec('mds\..*'); | |
a34866f0 DM |
156 | &$cond_write_sec('mon'); |
157 | &$cond_write_sec('osd'); | |
158 | &$cond_write_sec('mon\..*'); | |
159 | &$cond_write_sec('osd\..*'); | |
160 | ||
161 | PVE::Tools::file_set_contents($pve_ceph_cfgpath, $out); | |
162 | } | |
163 | ||
164 | sub setup_pve_symlinks { | |
165 | # fail if we find a real file instead of a link | |
166 | if (-f $ceph_cfgpath) { | |
167 | my $lnk = readlink($ceph_cfgpath); | |
168 | die "file '$ceph_cfgpath' already exists\n" | |
169 | if !$lnk || $lnk ne $pve_ceph_cfgpath; | |
170 | } else { | |
171 | symlink($pve_ceph_cfgpath, $ceph_cfgpath) || | |
172 | die "unable to create symlink '$ceph_cfgpath' - $!\n"; | |
173 | } | |
174 | } | |
175 | ||
176 | sub ceph_service_cmd { | |
2bfacbcf AD |
177 | my ($action, $service) = @_; |
178 | ||
1aecf972 | 179 | if (systemd_managed()) { |
2bfacbcf AD |
180 | |
181 | if ($service && $service =~ m/^(mon|osd|mds|radosgw)(\.([A-Za-z0-9]{1,32}))?$/) { | |
182 | $service = defined($3) ? "ceph-$1\@$3" : "ceph-$1.target"; | |
183 | } else { | |
184 | $service = "ceph.target"; | |
185 | } | |
186 | ||
187 | PVE::Tools::run_command(['/bin/systemctl', $action, $service]); | |
188 | ||
189 | } else { | |
190 | # ceph daemons does not call 'setsid', so we do that ourself | |
6f8bf83d | 191 | # (fork_worker send KILL to whole process group) |
2bfacbcf AD |
192 | PVE::Tools::run_command(['setsid', 'service', 'ceph', '-c', $pve_ceph_cfgpath, $action, $service]); |
193 | } | |
a34866f0 DM |
194 | } |
195 | ||
1aecf972 WL |
196 | # Ceph versions greater Hammer use 'ceph' as user and group instead |
197 | # of 'root', and use systemd. | |
198 | sub systemd_managed { | |
199 | ||
200 | if (-f "/lib/systemd/system/ceph-osd\@.service") { | |
201 | return 1; | |
202 | } else { | |
203 | return 0; | |
204 | } | |
205 | } | |
206 | ||
a34866f0 | 207 | 1; |