]>
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); | |
20 | use PVE::CephTools; | |
21 | use PVE::API2::Ceph; | |
7e1a9d25 | 22 | use PVE::API2::Ceph::FS; |
b82649cc | 23 | use PVE::API2::Ceph::MDS; |
3e8560ac DM |
24 | |
25 | use PVE::CLIHandler; | |
26 | ||
27 | use base qw(PVE::CLIHandler); | |
28 | ||
29 | my $nodename = PVE::INotify::nodename(); | |
30 | ||
31 | my $upid_exit = sub { | |
32 | my $upid = shift; | |
33 | my $status = PVE::Tools::upid_read_status($upid); | |
34 | exit($status eq 'OK' ? 0 : -1); | |
35 | }; | |
36 | ||
7e017024 DM |
37 | sub setup_environment { |
38 | PVE::RPCEnvironment->setup_default_cli_env(); | |
39 | } | |
40 | ||
3e8560ac DM |
41 | __PACKAGE__->register_method ({ |
42 | name => 'purge', | |
43 | path => 'purge', | |
44 | method => 'POST', | |
45 | description => "Destroy ceph related data and configuration files.", | |
46 | parameters => { | |
47 | additionalProperties => 0, | |
48 | properties => { | |
49 | }, | |
50 | }, | |
51 | returns => { type => 'null' }, | |
52 | code => sub { | |
53 | my ($param) = @_; | |
54 | ||
55 | my $monstat; | |
56 | ||
57 | eval { | |
58 | my $rados = PVE::RADOS->new(); | |
59 | my $monstat = $rados->mon_command({ prefix => 'mon_status' }); | |
60 | }; | |
61 | my $err = $@; | |
62 | ||
63 | die "detected running ceph services- unable to purge data\n" | |
64 | if !$err; | |
65 | ||
66 | # fixme: this is dangerous - should we really support this function? | |
67 | PVE::CephTools::purge_all_ceph_files(); | |
68 | ||
69 | return undef; | |
70 | }}); | |
71 | ||
72 | __PACKAGE__->register_method ({ | |
73 | name => 'install', | |
74 | path => 'install', | |
75 | method => 'POST', | |
76 | description => "Install ceph related packages.", | |
77 | parameters => { | |
78 | additionalProperties => 0, | |
79 | properties => { | |
80 | version => { | |
81 | type => 'string', | |
caf37855 FG |
82 | #enum => ['hammer', 'jewel'], # for jessie |
83 | enum => ['luminous',], # for stretch | |
3e8560ac DM |
84 | optional => 1, |
85 | } | |
86 | }, | |
87 | }, | |
88 | returns => { type => 'null' }, | |
89 | code => sub { | |
90 | my ($param) = @_; | |
91 | ||
caf37855 | 92 | my $cephver = $param->{version} || 'luminous'; |
3e8560ac DM |
93 | |
94 | local $ENV{DEBIAN_FRONTEND} = 'noninteractive'; | |
95 | ||
caf37855 FG |
96 | if ($cephver eq 'luminous') { |
97 | PVE::Tools::file_set_contents("/etc/apt/sources.list.d/ceph.list", | |
9cf3e449 | 98 | "deb http://download.proxmox.com/debian/ceph-luminous stretch main\n"); |
caf37855 FG |
99 | } else { |
100 | # use fixed devel repo for now, because there is no officila repo for jessie | |
101 | my $devrepo = undef; | |
102 | ||
103 | my $keyurl = $devrepo ? | |
104 | "https://git.ceph.com/?p=ceph.git;a=blob_plain;f=keys/autobuild.asc" : | |
105 | "https://git.ceph.com/?p=ceph.git;a=blob_plain;f=keys/release.asc"; | |
106 | ||
107 | print "download and import ceph repository keys\n"; | |
108 | ||
109 | # Note: wget on Debian wheezy cannot handle new ceph.com certificates, so | |
110 | # we use LWP::UserAgent | |
111 | #system("wget -q -O- '$keyurl'| apt-key add - 2>&1 >/dev/null") == 0 || | |
112 | #die "unable to download ceph release key\n"; | |
113 | ||
114 | my $tmp_key_file = "/tmp/ceph-release-keys.asc"; | |
115 | my $ua = LWP::UserAgent->new(protocols_allowed => ['http', 'https'], timeout => 120); | |
116 | $ua->env_proxy; | |
117 | my $response = $ua->get($keyurl); | |
118 | if ($response->is_success) { | |
119 | my $data = $response->decoded_content; | |
120 | PVE::Tools::file_set_contents($tmp_key_file, $data); | |
121 | } else { | |
122 | die "unable to download ceph release key: " . $response->status_line . "\n"; | |
123 | } | |
3e8560ac | 124 | |
caf37855 FG |
125 | system("apt-key add $tmp_key_file 2>&1 >/dev/null") == 0 || |
126 | die "unable to download ceph release key\n"; | |
3e8560ac | 127 | |
caf37855 | 128 | unlink $tmp_key_file; |
3e8560ac | 129 | |
caf37855 FG |
130 | my $source = $devrepo ? |
131 | "deb http://gitbuilder.ceph.com/ceph-deb-jessie-x86_64-basic/ref/$devrepo jessie main\n" : | |
132 | "deb http://download.ceph.com/debian-$cephver jessie main\n"; | |
3e8560ac | 133 | |
caf37855 FG |
134 | PVE::Tools::file_set_contents("/etc/apt/sources.list.d/ceph.list", $source); |
135 | } | |
3e8560ac DM |
136 | |
137 | print "update available package list\n"; | |
138 | eval { run_command(['apt-get', '-q', 'update'], outfunc => sub {}, errfunc => sub {}); }; | |
139 | ||
17325396 DM |
140 | system('apt-get', '--no-install-recommends', |
141 | '-o', 'Dpkg::Options::=--force-confnew', | |
142 | 'install', '--', | |
143 | 'ceph', 'ceph-common', 'gdisk'); | |
3e8560ac | 144 | |
ab1213cc FG |
145 | if (PVE::CephTools::systemd_managed() && ! -e '/etc/systemd/system/ceph.service') { |
146 | #to disable old SysV init scripts. | |
147 | print "replacing ceph init script with own ceph.service\n"; | |
148 | eval { | |
149 | PVE::Tools::run_command('cp -v /usr/share/doc/pve-manager/examples/ceph.service /etc/systemd/system/ceph.service'); | |
150 | PVE::Tools::run_command('systemctl daemon-reload'); | |
151 | PVE::Tools::run_command('systemctl enable ceph.service'); | |
152 | }; | |
153 | warn "could not install ceph.service\n" if $@; | |
154 | } | |
155 | ||
3e8560ac DM |
156 | return undef; |
157 | }}); | |
158 | ||
159 | our $cmddef = { | |
160 | init => [ 'PVE::API2::Ceph', 'init', [], { node => $nodename } ], | |
161 | lspools => [ 'PVE::API2::Ceph', 'lspools', [], { node => $nodename }, sub { | |
162 | my $res = shift; | |
163 | ||
180d612b AA |
164 | printf("%-20s %10s %10s %10s %10s %20s\n", "Name", "size", "min_size", |
165 | "pg_num", "%-used", "used"); | |
3e8560ac | 166 | foreach my $p (sort {$a->{pool_name} cmp $b->{pool_name}} @$res) { |
180d612b AA |
167 | printf("%-20s %10d %10d %10d %10.2f %20d\n", $p->{pool_name}, |
168 | $p->{size}, $p->{min_size}, $p->{pg_num}, | |
169 | $p->{percent_used}, $p->{bytes_used}); | |
3e8560ac DM |
170 | } |
171 | }], | |
172 | createpool => [ 'PVE::API2::Ceph', 'createpool', ['name'], { node => $nodename }], | |
173 | destroypool => [ 'PVE::API2::Ceph', 'destroypool', ['name'], { node => $nodename } ], | |
7e1a9d25 | 174 | createfs => [ 'PVE::API2::Ceph::FS', 'createfs', [], { node => $nodename }], |
3e8560ac DM |
175 | createosd => [ 'PVE::API2::CephOSD', 'createosd', ['dev'], { node => $nodename }, $upid_exit], |
176 | destroyosd => [ 'PVE::API2::CephOSD', 'destroyosd', ['osdid'], { node => $nodename }, $upid_exit], | |
177 | createmon => [ 'PVE::API2::Ceph', 'createmon', [], { node => $nodename }, $upid_exit], | |
178 | destroymon => [ 'PVE::API2::Ceph', 'destroymon', ['monid'], { node => $nodename }, $upid_exit], | |
ca68ac3e DC |
179 | createmgr => [ 'PVE::API2::Ceph', 'createmgr', [], { node => $nodename }, $upid_exit], |
180 | destroymgr => [ 'PVE::API2::Ceph', 'destroymgr', ['id'], { node => $nodename }, $upid_exit], | |
b82649cc TL |
181 | createmds => [ 'PVE::API2::Ceph::MDS', 'createmds', [], { node => $nodename }, $upid_exit], |
182 | destroymds => [ 'PVE::API2::Ceph::MDS', 'destroymds', ['id'], { node => $nodename }, $upid_exit], | |
3e8560ac DM |
183 | start => [ 'PVE::API2::Ceph', 'start', ['service'], { node => $nodename }, $upid_exit], |
184 | stop => [ 'PVE::API2::Ceph', 'stop', ['service'], { node => $nodename }, $upid_exit], | |
185 | install => [ __PACKAGE__, 'install', [] ], | |
186 | purge => [ __PACKAGE__, 'purge', [] ], | |
187 | status => [ 'PVE::API2::Ceph', 'status', [], { node => $nodename }, sub { | |
188 | my $res = shift; | |
189 | my $json = JSON->new->allow_nonref; | |
190 | print $json->pretty->encode($res) . "\n"; | |
191 | }], | |
192 | }; | |
193 | ||
194 | 1; |