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