]>
Commit | Line | Data |
---|---|---|
3e8560ac DM |
1 | package PVE::CLI::pveceph; |
2 | ||
3 | use strict; | |
4 | use warnings; | |
5 | ||
6 | use Fcntl ':flock'; | |
7 | use File::Path; | |
8 | use IO::File; | |
9 | use JSON; | |
10 | use Data::Dumper; | |
11 | use LWP::UserAgent; | |
12 | ||
13 | use PVE::SafeSyslog; | |
14 | use PVE::Cluster; | |
15 | use PVE::INotify; | |
16 | use PVE::RPCEnvironment; | |
17 | use PVE::Storage; | |
18 | use PVE::Tools qw(run_command); | |
19 | use PVE::JSONSchema qw(get_standard_option); | |
6fb08cb9 | 20 | use PVE::Ceph::Tools; |
3e8560ac | 21 | use PVE::API2::Ceph; |
7e1a9d25 | 22 | use PVE::API2::Ceph::FS; |
b82649cc | 23 | use PVE::API2::Ceph::MDS; |
4fec2764 | 24 | use PVE::API2::Ceph::MGR; |
98fe93ae | 25 | use PVE::API2::Ceph::MON; |
79fa41a2 | 26 | use PVE::API2::Ceph::OSD; |
3e8560ac DM |
27 | |
28 | use PVE::CLIHandler; | |
29 | ||
30 | use base qw(PVE::CLIHandler); | |
31 | ||
32 | my $nodename = PVE::INotify::nodename(); | |
33 | ||
34 | my $upid_exit = sub { | |
35 | my $upid = shift; | |
36 | my $status = PVE::Tools::upid_read_status($upid); | |
37 | exit($status eq 'OK' ? 0 : -1); | |
38 | }; | |
39 | ||
7e017024 DM |
40 | sub setup_environment { |
41 | PVE::RPCEnvironment->setup_default_cli_env(); | |
42 | } | |
43 | ||
3e8560ac DM |
44 | __PACKAGE__->register_method ({ |
45 | name => 'purge', | |
46 | path => 'purge', | |
47 | method => 'POST', | |
48 | description => "Destroy ceph related data and configuration files.", | |
49 | parameters => { | |
50 | additionalProperties => 0, | |
51 | properties => { | |
52 | }, | |
53 | }, | |
54 | returns => { type => 'null' }, | |
55 | code => sub { | |
56 | my ($param) = @_; | |
57 | ||
58 | my $monstat; | |
59 | ||
60 | eval { | |
61 | my $rados = PVE::RADOS->new(); | |
62 | my $monstat = $rados->mon_command({ prefix => 'mon_status' }); | |
63 | }; | |
64 | my $err = $@; | |
65 | ||
66 | die "detected running ceph services- unable to purge data\n" | |
67 | if !$err; | |
68 | ||
69 | # fixme: this is dangerous - should we really support this function? | |
6fb08cb9 | 70 | PVE::Ceph::Tools::purge_all_ceph_files(); |
3e8560ac DM |
71 | |
72 | return undef; | |
73 | }}); | |
74 | ||
75 | __PACKAGE__->register_method ({ | |
76 | name => 'install', | |
77 | path => 'install', | |
78 | method => 'POST', | |
79 | description => "Install ceph related packages.", | |
80 | parameters => { | |
81 | additionalProperties => 0, | |
82 | properties => { | |
83 | version => { | |
84 | type => 'string', | |
c3d9c698 TL |
85 | # for buster, luminous kept for testing/upgrade purposes only! - FIXME: remove with 6.2? |
86 | enum => ['luminous', 'nautilus',], | |
87 | default => 'nautilus', | |
88 | description => "Ceph version to install.", | |
3e8560ac DM |
89 | optional => 1, |
90 | } | |
91 | }, | |
92 | }, | |
93 | returns => { type => 'null' }, | |
94 | code => sub { | |
95 | my ($param) = @_; | |
96 | ||
c3d9c698 TL |
97 | my $default_vers = 'nautilus'; |
98 | my $cephver = $param->{version} || $default_vers; | |
3e8560ac | 99 | |
c3d9c698 TL |
100 | my $repolist; |
101 | if ($cephver eq 'nautilus') { | |
102 | $repolist = "deb http://download.proxmox.com/debian/ceph-nautilus buster main\n"; | |
103 | # FIXME: remove non-public testing repo | |
104 | $repolist = "deb http://repo.proxmox.com/staging/ceph-nautilus buster ceph-14.0\n"; | |
105 | } elsif ($cephver eq 'luminous') { | |
106 | $repolist = "deb http://download.proxmox.com/debian/ceph-luminous buster main\n"; | |
caf37855 | 107 | } else { |
36d5ee12 | 108 | die "not implemented ceph version: $cephver"; |
caf37855 | 109 | } |
c3d9c698 TL |
110 | PVE::Tools::file_set_contents("/etc/apt/sources.list.d/ceph.list", $repolist); |
111 | ||
112 | warn "WARNING: installing non-default ceph release '$cephver'!\n\n" if $cephver ne $default_vers; | |
3e8560ac | 113 | |
87166f36 | 114 | local $ENV{DEBIAN_FRONTEND} = 'noninteractive'; |
3e8560ac | 115 | print "update available package list\n"; |
87166f36 | 116 | eval { run_command(['apt-get', '-q', 'update'], outfunc => sub {}, errfunc => sub { print STDERR "$_[0]\n" }) }; |
3e8560ac | 117 | |
2ca75379 TL |
118 | my @apt_install = qw(apt-get --no-install-recommends -o Dpkg::Options::=--force-confnew install --); |
119 | my @ceph_packages = qw( | |
120 | ceph | |
121 | ceph-common | |
122 | ceph-mds | |
123 | ceph-fuse | |
124 | gdisk | |
125 | ); | |
126 | ||
55ab726e | 127 | print "start installation\n"; |
2ca75379 TL |
128 | if (system(@apt_install, @ceph_packages) != 0) { |
129 | die "apt failed during ceph installation ($?)\n"; | |
130 | } | |
55ab726e TL |
131 | |
132 | print "\ninstalled ceph $cephver successfully\n"; | |
3e8560ac | 133 | |
bba5c712 | 134 | if (! -e '/etc/systemd/system/ceph.service') { |
1b364b3a | 135 | print "\nreplacing ceph init script with own ceph.service\n"; |
ab1213cc | 136 | eval { |
13f0b446 TL |
137 | run_command('cp -v /usr/share/doc/pve-manager/examples/ceph.service /etc/systemd/system/ceph.service'); |
138 | run_command('systemctl daemon-reload'); | |
139 | run_command('systemctl enable ceph.service'); | |
ab1213cc | 140 | }; |
588c0a75 TL |
141 | if (my $err = $@) { |
142 | warn "WARNING: could not install ceph.service: $@\n"; | |
1b364b3a | 143 | } else { |
588c0a75 | 144 | print "installed ceph.service successfully\n"; |
1b364b3a | 145 | } |
ab1213cc FG |
146 | } |
147 | ||
3e8560ac DM |
148 | return undef; |
149 | }}); | |
150 | ||
151 | our $cmddef = { | |
152 | init => [ 'PVE::API2::Ceph', 'init', [], { node => $nodename } ], | |
8c476782 TL |
153 | pool => { |
154 | ls => [ 'PVE::API2::Ceph', 'lspools', [], { node => $nodename }, sub { | |
155 | my $res = shift; | |
156 | ||
157 | printf("%-20s %10s %10s %10s %10s %20s\n", "Name", "size", "min_size", | |
158 | "pg_num", "%-used", "used"); | |
159 | foreach my $p (sort {$a->{pool_name} cmp $b->{pool_name}} @$res) { | |
160 | printf("%-20s %10d %10d %10d %10.2f %20d\n", $p->{pool_name}, | |
161 | $p->{size}, $p->{min_size}, $p->{pg_num}, | |
162 | $p->{percent_used}, $p->{bytes_used}); | |
163 | } | |
164 | }], | |
165 | create => [ 'PVE::API2::Ceph', 'createpool', ['name'], { node => $nodename }], | |
166 | destroy => [ 'PVE::API2::Ceph', 'destroypool', ['name'], { node => $nodename } ], | |
167 | }, | |
168 | lspools => { alias => 'pool ls' }, | |
169 | createpool => { alias => 'pool create' }, | |
170 | destroypool => { alias => 'pool destroy' }, | |
171 | fs => { | |
172 | create => [ 'PVE::API2::Ceph::FS', 'createfs', [], { node => $nodename }], | |
173 | }, | |
174 | osd => { | |
79fa41a2 DC |
175 | create => [ 'PVE::API2::Ceph::OSD', 'createosd', ['dev'], { node => $nodename }, $upid_exit], |
176 | destroy => [ 'PVE::API2::Ceph::OSD', 'destroyosd', ['osdid'], { node => $nodename }, $upid_exit], | |
8c476782 TL |
177 | }, |
178 | createosd => { alias => 'osd create' }, | |
179 | destroyosd => { alias => 'osd destroy' }, | |
180 | mon => { | |
98fe93ae DC |
181 | create => [ 'PVE::API2::Ceph::MON', 'createmon', [], { node => $nodename }, $upid_exit], |
182 | destroy => [ 'PVE::API2::Ceph::MON', 'destroymon', ['monid'], { node => $nodename }, $upid_exit], | |
8c476782 TL |
183 | }, |
184 | createmon => { alias => 'mon create' }, | |
185 | destroymon => { alias => 'mon destroy' }, | |
186 | mgr => { | |
4fec2764 DC |
187 | create => [ 'PVE::API2::Ceph::MGR', 'createmgr', [], { node => $nodename }, $upid_exit], |
188 | destroy => [ 'PVE::API2::Ceph::MGR', 'destroymgr', ['id'], { node => $nodename }, $upid_exit], | |
8c476782 TL |
189 | }, |
190 | createmgr => { alias => 'mgr create' }, | |
191 | destroymgr => { alias => 'mgr destroy' }, | |
192 | mds => { | |
193 | create => [ 'PVE::API2::Ceph::MDS', 'createmds', [], { node => $nodename }, $upid_exit], | |
f16bb531 | 194 | destroy => [ 'PVE::API2::Ceph::MDS', 'destroymds', ['name'], { node => $nodename }, $upid_exit], |
8c476782 | 195 | }, |
3e8560ac DM |
196 | start => [ 'PVE::API2::Ceph', 'start', ['service'], { node => $nodename }, $upid_exit], |
197 | stop => [ 'PVE::API2::Ceph', 'stop', ['service'], { node => $nodename }, $upid_exit], | |
198 | install => [ __PACKAGE__, 'install', [] ], | |
199 | purge => [ __PACKAGE__, 'purge', [] ], | |
200 | status => [ 'PVE::API2::Ceph', 'status', [], { node => $nodename }, sub { | |
201 | my $res = shift; | |
202 | my $json = JSON->new->allow_nonref; | |
203 | print $json->pretty->encode($res) . "\n"; | |
204 | }], | |
205 | }; | |
206 | ||
207 | 1; |