]>
Commit | Line | Data |
---|---|---|
b82649cc TL |
1 | package PVE::API2::Ceph::MDS; |
2 | ||
3 | use strict; | |
4 | use warnings; | |
5 | ||
6fb08cb9 | 6 | use PVE::Ceph::Tools; |
27439be6 | 7 | use PVE::Ceph::Services; |
c31f487e | 8 | use PVE::Cluster qw(cfs_read_file cfs_write_file); |
b82649cc TL |
9 | use PVE::INotify; |
10 | use PVE::JSONSchema qw(get_standard_option); | |
11 | use PVE::RADOS; | |
12 | use PVE::RESTHandler; | |
13 | use PVE::RPCEnvironment; | |
14 | ||
15 | use base qw(PVE::RESTHandler); | |
16 | ||
17 | __PACKAGE__->register_method ({ | |
18 | name => 'index', | |
19 | path => '', | |
20 | method => 'GET', | |
21 | description => "MDS directory index.", | |
22 | permissions => { | |
23 | check => ['perm', '/', [ 'Sys.Audit', 'Datastore.Audit' ], any => 1], | |
24 | }, | |
25 | proxyto => 'node', | |
26 | protected => 1, | |
27 | parameters => { | |
28 | additionalProperties => 0, | |
29 | properties => { | |
30 | node => get_standard_option('pve-node'), | |
31 | }, | |
32 | }, | |
33 | returns => { | |
34 | type => 'array', | |
35 | items => { | |
36 | type => "object", | |
37 | properties => { | |
38 | name => { | |
39 | description => "The name (ID) for the MDS", | |
40 | }, | |
41 | addr => { | |
42 | type => 'string', | |
43 | optional => 1, | |
44 | }, | |
45 | host => { | |
46 | type => 'string', | |
47 | optional => 1, | |
48 | }, | |
49 | state => { | |
50 | type => 'string', | |
51 | description => 'State of the MDS', | |
52 | }, | |
53 | standby_replay => { | |
54 | type => 'boolean', | |
55 | optional => 1, | |
56 | description => 'If true, the standby MDS is polling the active MDS for faster recovery (hot standby).', | |
57 | }, | |
58 | rank => { | |
59 | type => 'integer', | |
60 | optional => 1, | |
61 | }, | |
62 | }, | |
63 | }, | |
64 | links => [ { rel => 'child', href => "{name}" } ], | |
65 | }, | |
66 | code => sub { | |
67 | my ($param) = @_; | |
68 | ||
6fb08cb9 | 69 | PVE::Ceph::Tools::check_ceph_inited(); |
1aa902ae | 70 | |
b82649cc TL |
71 | my $res = []; |
72 | ||
c31f487e | 73 | my $cfg = cfs_read_file('ceph.conf'); |
d5373b7d | 74 | my $rados = PVE::RADOS->new(); |
b82649cc | 75 | |
d5373b7d | 76 | my $mds_hash = PVE::Ceph::Services::get_services_info("mds", $cfg, $rados); |
b82649cc | 77 | |
d5373b7d | 78 | my $mds_state = PVE::Ceph::Services::get_cluster_mds_state($rados); |
b82649cc TL |
79 | foreach my $name (keys %$mds_state) { |
80 | my $d = $mds_state->{$name}; | |
81 | # just overwrite, this always provides more info | |
82 | $mds_hash->{$name}->{$_} = $d->{$_} for keys %$d; | |
83 | } | |
84 | ||
85 | return PVE::RESTHandler::hash_to_array($mds_hash, 'name'); | |
86 | } | |
87 | }); | |
88 | ||
89 | __PACKAGE__->register_method ({ | |
90 | name => 'createmds', | |
91 | path => '{name}', | |
92 | method => 'POST', | |
93 | description => "Create Ceph Metadata Server (MDS)", | |
94 | proxyto => 'node', | |
95 | protected => 1, | |
96 | permissions => { | |
97 | check => ['perm', '/', [ 'Sys.Modify' ]], | |
98 | }, | |
99 | parameters => { | |
100 | additionalProperties => 0, | |
101 | properties => { | |
102 | node => get_standard_option('pve-node'), | |
103 | name => { | |
104 | type => 'string', | |
105 | optional => 1, | |
106 | default => 'nodename', | |
107 | pattern => '[a-zA-Z0-9]([a-zA-Z0-9\-]*[a-zA-Z0-9])?', | |
108 | description => "The ID for the mds, when omitted the same as the nodename", | |
109 | }, | |
110 | hotstandby => { | |
111 | type => 'boolean', | |
112 | optional => 1, | |
113 | default => '0', | |
114 | description => "Determines whether a ceph-mds daemon should poll and replay the log of an active MDS. ". | |
115 | "Faster switch on MDS failure, but needs more idle resources.", | |
116 | }, | |
117 | }, | |
118 | }, | |
119 | returns => { type => 'string' }, | |
120 | code => sub { | |
121 | my ($param) = @_; | |
122 | ||
6fb08cb9 | 123 | PVE::Ceph::Tools::check_ceph_installed('ceph_mds'); |
b82649cc | 124 | |
6fb08cb9 | 125 | PVE::Ceph::Tools::check_ceph_inited(); |
b82649cc TL |
126 | |
127 | my $rpcenv = PVE::RPCEnvironment::get(); | |
128 | my $authuser = $rpcenv->get_user(); | |
129 | ||
130 | my $nodename = $param->{node}; | |
131 | $nodename = INotify::nodename() if $nodename eq 'localhost'; | |
132 | ||
133 | my $mds_id = $param->{name} // $nodename; | |
134 | ||
135 | my $worker = sub { | |
6fb08cb9 | 136 | my $timeout = PVE::Ceph::Tools::get_config('long_rados_timeout'); |
b82649cc TL |
137 | my $rados = PVE::RADOS->new(timeout => $timeout); |
138 | ||
c31f487e | 139 | my $cfg = cfs_read_file('ceph.conf'); |
b82649cc TL |
140 | |
141 | my $section = "mds.$mds_id"; | |
142 | ||
143 | if (defined($cfg->{$section})) { | |
144 | die "MDS '$mds_id' already referenced in ceph config, abort!\n" | |
145 | } | |
146 | ||
147 | if (!defined($cfg->{mds}->{keyring})) { | |
148 | # $id isn't a perl variable but a ceph metavariable | |
149 | my $keyring = '/var/lib/ceph/mds/ceph-$id/keyring'; | |
150 | ||
151 | $cfg->{mds}->{keyring} = $keyring; | |
152 | } | |
153 | ||
154 | $cfg->{$section}->{host} = $nodename; | |
155 | $cfg->{$section}->{"mds standby for name"} = 'pve'; | |
156 | ||
157 | if ($param->{hotstandby}) { | |
158 | $cfg->{$section}->{"mds standby replay"} = 'true'; | |
159 | } | |
160 | ||
c31f487e | 161 | cfs_write_file('ceph.conf', $cfg); |
b82649cc | 162 | |
27439be6 | 163 | eval { PVE::Ceph::Services::create_mds($mds_id, $rados) }; |
b82649cc TL |
164 | if (my $err = $@) { |
165 | # we abort early if the section is defined, so we know that we | |
166 | # wrote it at this point. Do not auto remove the service, could | |
167 | # do real harm for previously manual setup MDS | |
168 | warn "Encountered error, remove '$section' from ceph.conf\n"; | |
c31f487e | 169 | my $cfg = cfs_read_file('ceph.conf'); |
b82649cc | 170 | delete $cfg->{$section}; |
c31f487e | 171 | cfs_write_file('ceph.conf', $cfg); |
b82649cc TL |
172 | |
173 | die "$err\n"; | |
174 | } | |
175 | }; | |
176 | ||
177 | return $rpcenv->fork_worker('cephcreatemds', "mds.$mds_id", $authuser, $worker); | |
178 | } | |
179 | }); | |
180 | ||
181 | __PACKAGE__->register_method ({ | |
182 | name => 'destroymds', | |
183 | path => '{name}', | |
184 | method => 'DELETE', | |
185 | description => "Destroy Ceph Metadata Server", | |
186 | proxyto => 'node', | |
187 | protected => 1, | |
188 | permissions => { | |
189 | check => ['perm', '/', [ 'Sys.Modify' ]], | |
190 | }, | |
191 | parameters => { | |
192 | additionalProperties => 0, | |
193 | properties => { | |
194 | node => get_standard_option('pve-node'), | |
195 | name => { | |
196 | description => 'The name (ID) of the mds', | |
197 | type => 'string', | |
198 | pattern => '[a-zA-Z0-9]([a-zA-Z0-9\-]*[a-zA-Z0-9])?', | |
199 | }, | |
200 | }, | |
201 | }, | |
202 | returns => { type => 'string' }, | |
203 | code => sub { | |
204 | my ($param) = @_; | |
205 | ||
206 | my $rpcenv = PVE::RPCEnvironment::get(); | |
207 | ||
208 | my $authuser = $rpcenv->get_user(); | |
209 | ||
6fb08cb9 | 210 | PVE::Ceph::Tools::check_ceph_inited(); |
b82649cc TL |
211 | |
212 | my $mds_id = $param->{name}; | |
213 | ||
214 | my $worker = sub { | |
6fb08cb9 | 215 | my $timeout = PVE::Ceph::Tools::get_config('long_rados_timeout'); |
b82649cc TL |
216 | my $rados = PVE::RADOS->new(timeout => $timeout); |
217 | ||
c31f487e | 218 | my $cfg = cfs_read_file('ceph.conf'); |
b82649cc TL |
219 | |
220 | if (defined($cfg->{"mds.$mds_id"})) { | |
221 | delete $cfg->{"mds.$mds_id"}; | |
c31f487e | 222 | cfs_write_file('ceph.conf', $cfg); |
b82649cc TL |
223 | } |
224 | ||
27439be6 | 225 | PVE::Ceph::Services::destroy_mds($mds_id, $rados); |
b82649cc TL |
226 | }; |
227 | ||
228 | return $rpcenv->fork_worker('cephdestroymds', "mds.$mds_id", $authuser, $worker); | |
229 | } | |
230 | }); | |
231 | ||
232 | 1; |