]>
git.proxmox.com Git - librados2-perl.git/blob - PVE/RADOS.pm
463abc785398ffabd33e0c62b2111418d790f143
11 use PVE
::RPCEnvironment
;
15 my $rados_default_timeout = 5;
16 my $ceph_default_conf = '/etc/pve/ceph.conf';
17 my $ceph_default_user = 'admin';
20 our @ISA = qw(Exporter);
22 # Items to export into callers namespace by default. Note: do not export
23 # names by default without a very good reason. Use EXPORT_OK instead.
24 # Do not simply export all your public functions/methods/constants.
26 # This allows declaration use PVE::RADOS ':all';
27 # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
29 our %EXPORT_TAGS = ( 'all' => [ qw(
33 our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
42 XSLoader
::load
('PVE::RADOS', $VERSION);
45 my ($fh, $cmd, $data) = @_;
47 local $SIG{PIPE
} = 'IGNORE';
49 my $bin = pack "a L/a*", $cmd, $data || '';
50 my $res = syswrite $fh, $bin;
52 die "write data failed - $!\n" if !defined($res);
56 my ($fh, $allow_eof) = @_;
60 local $SIG{PIPE
} = 'IGNORE';
62 while (length($head) < 5) {
63 last if !sysread $fh, $head, 5 - length($head), length($head);
65 return undef if $allow_eof && length($head) == 0;
67 die "partial read\n" if length($head) < 5;
69 my ($cmd, $len) = unpack "a L", $head;
72 while (length($data) < $len) {
73 last if !sysread $fh, $data, $len - length($data), length($data);
75 die "partial data read\n" if length($data) < $len;
77 return wantarray ?
($cmd, $data) : $data;
80 my $kill_worker = sub {
83 return if !$self->{cpid
};
84 return if $self->{__already_killed
};
86 $self->{__already_killed
} = 1;
88 close($self->{child
}) if defined($self->{child
});
90 # only kill if we created the process
91 return if $self->{pid
} != $$;
93 kill(9, $self->{cpid
});
94 waitpid($self->{cpid
}, 0);
98 my ($self, $cmd, $data, $expect_tag) = @_;
100 $expect_tag = '>' if !$expect_tag;
102 die "detected forked connection\n" if $self->{pid
} != $$;
106 &$writedata($self->{child
}, $cmd, $data) if $expect_tag ne 'S';
107 ($restag, $raw) = &$readdata($self->{child
});
109 eval { PVE
::Tools
::run_with_timeout
($self->{timeout
}, $code); };
111 &$kill_worker($self);
114 if ($restag eq 'E') {
116 die "unknown error\n";
119 die "got unexpected result\n" if $restag ne $expect_tag;
125 my ($class, %params) = @_;
127 my $rpcenv = PVE
::RPCEnvironment
::get
();
129 socketpair(my $child, my $parent, AF_UNIX
, SOCK_STREAM
, PF_UNSPEC
)
130 || die "socketpair: $!\n";
134 die "unable to fork - $!\n" if !defined($cpid);
138 my $timeout = delete $params{timeout
} || $rados_default_timeout;
140 $self->{timeout
} = $timeout;
143 if ($cpid) { # parent
146 $self->{cpid
} = $cpid;
147 $self->{child
} = $child;
149 &$sendcmd($self, undef, undef, 'S'); # wait for sync
154 PVE
::INotify
::inotify_close
();
156 if (my $atfork = $rpcenv->{atfork
}) {
166 my $ceph_user = delete $params{userid
} || $ceph_default_user;
167 $conn = pve_rados_create
($ceph_user) ||
168 die "unable to create RADOS object\n";
170 if (defined($params{ceph_conf
}) && (!-e
$params{ceph_conf
})) {
171 die "Supplied ceph config doesn't exist, $params{ceph_conf}\n";
174 my $ceph_conf = delete $params{ceph_conf
} || $ceph_default_conf;
177 pve_rados_conf_read_file
($conn, $ceph_conf);
180 pve_rados_conf_set
($conn, 'client_mount_timeout', $timeout);
182 foreach my $k (keys %params) {
183 pve_rados_conf_set
($conn, $k, $params{$k});
186 pve_rados_connect
($conn);
189 &$writedata($parent, 'E', $err);
192 &$writedata($parent, 'S');
194 $self->{conn
} = $conn;
197 my ($cmd, $data) = &$readdata($parent, 1);
199 last if !$cmd || $cmd eq 'Q';
203 if ($cmd eq 'M') { # rados monitor commands
204 $res = pve_rados_mon_command
($self->{conn
}, [ $data ]);
205 } elsif ($cmd eq 'C') { # class methods
206 my $aref = decode_json
($data);
207 my $method = shift @$aref;
208 $res = encode_json
($self->$method(@$aref));
210 die "invalid command\n";
214 &$writedata($parent, 'E', $err);
217 &$writedata($parent, '>', $res);
227 my ($self, $new_timeout) = @_;
229 $self->{timeout
} = $new_timeout if $new_timeout;
231 return $self->{timeout
};
238 #print "$$: DESTROY WAIT0\n";
239 &$kill_worker($self);
240 #print "$$: DESTROY WAIT\n";
242 #print "$$: DESTROY SHUTDOWN\n";
243 pve_rados_shutdown
($self->{conn
}) if $self->{conn
};
248 my ($self, @args) = @_;
251 my $data = encode_json
(['cluster_stat', @args]);
252 my $raw = &$sendcmd($self, 'C', $data);
253 return decode_json
($raw);
255 return pve_rados_cluster_stat
($self->{conn
});
259 # example1: { prefix => 'get_command_descriptions'})
260 # example2: { prefix => 'mon dump', format => 'json' }
262 my ($self, $cmd) = @_;
264 $cmd->{format
} = 'json' if !$cmd->{format
};
266 my $json = encode_json
($cmd);
268 my $raw = eval { $sendcmd->($self, 'M', $json) };
269 die "error with '$cmd->{prefix}': $@" if $@;
271 if ($cmd->{format
} && $cmd->{format
} eq 'json') {
272 return length($raw) ? decode_json
($raw) : undef;
283 PVE::RADOS - Perl bindings for librados
289 my $rados = PVE::RADOS::new();
290 my $stat = $rados->cluster_stat();
291 my $res = $rados->mon_command({ prefix => 'mon dump', format => 'json' });
295 Perl bindings for librados.
303 Dietmar Maurer, E<lt>dietmar@proxmox.com<gt>