]>
git.proxmox.com Git - librados2-perl.git/blob - PVE/RADOS.pm
11 use PVE
::RPCEnvironment
;
15 my $rados_default_timeout = 5;
18 our @ISA = qw(Exporter);
20 # Items to export into callers namespace by default. Note: do not export
21 # names by default without a very good reason. Use EXPORT_OK instead.
22 # Do not simply export all your public functions/methods/constants.
24 # This allows declaration use PVE::RADOS ':all';
25 # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
27 our %EXPORT_TAGS = ( 'all' => [ qw(
31 our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
40 XSLoader
::load
('PVE::RADOS', $VERSION);
43 my ($fh, $cmd, $data) = @_;
45 local $SIG{PIPE
} = 'IGNORE';
47 my $bin = pack "a L/a*", $cmd, $data || '';
48 my $res = syswrite $fh, $bin;
50 die "write data failed - $!\n" if !defined($res);
54 my ($fh, $allow_eof) = @_;
58 local $SIG{PIPE
} = 'IGNORE';
60 while (length($head) < 5) {
61 last if !sysread $fh, $head, 5 - length($head), length($head);
63 return undef if $allow_eof && length($head) == 0;
65 die "partial read\n" if length($head) < 5;
67 my ($cmd, $len) = unpack "a L", $head;
70 while (length($data) < $len) {
71 last if !sysread $fh, $data, $len - length($data), length($data);
73 die "partial data read\n" if length($data) < $len;
75 return wantarray ?
($cmd, $data) : $data;
78 my $kill_worker = sub {
81 return if !$self->{cpid
};
82 return if $self->{__already_killed
};
84 $self->{__already_killed
} = 1;
86 close($self->{child
}) if defined($self->{child
});
88 # only kill if we created the process
89 return if $self->{pid
} != $$;
91 kill(9, $self->{cpid
});
92 waitpid($self->{cpid
}, 0);
96 my ($self, $cmd, $data, $expect_tag) = @_;
98 $expect_tag = '>' if !$expect_tag;
100 die "detected forked connection" if $self->{pid
} != $$;
104 &$writedata($self->{child
}, $cmd, $data) if $expect_tag ne 'S';
105 ($restag, $raw) = &$readdata($self->{child
});
107 eval { PVE
::Tools
::run_with_timeout
($self->{timeout
}, $code); };
109 &$kill_worker($self);
112 if ($restag eq 'E') {
114 die "unknown error\n";
117 die "got unexpected result\n" if $restag ne $expect_tag;
123 my ($class, %params) = @_;
125 my $rpcenv = PVE
::RPCEnvironment
::get
();
127 socketpair(my $child, my $parent, AF_UNIX
, SOCK_STREAM
, PF_UNSPEC
)
128 || die "socketpair: $!";
132 die "unable to fork - $!\n" if !defined($cpid);
136 my $timeout = delete $params{timeout
} || $rados_default_timeout;
138 $self->{timeout
} = $timeout;
141 if ($cpid) { # parent
144 $self->{cpid
} = $cpid;
145 $self->{child
} = $child;
147 &$sendcmd($self, undef, undef, 'S'); # wait for sync
152 PVE
::INotify
::inotify_close
();
154 if (my $atfork = $rpcenv->{atfork
}) {
164 $conn = pve_rados_create
() ||
165 die "unable to create RADOS object\n";
167 pve_rados_conf_set
($conn, 'client_mount_timeout', $timeout);
169 foreach my $k (keys %params) {
170 pve_rados_conf_set
($conn, $k, $params{$k});
173 pve_rados_connect
($conn);
176 &$writedata($parent, 'E', $err);
179 &$writedata($parent, 'S');
181 $self->{conn
} = $conn;
184 my ($cmd, $data) = &$readdata($parent, 1);
186 last if !$cmd || $cmd eq 'Q';
190 if ($cmd eq 'M') { # rados monitor commands
191 $res = pve_rados_mon_command
($self->{conn
}, [ $data ]);
192 } elsif ($cmd eq 'C') { # class methods
193 my $aref = decode_json
($data);
194 my $method = shift @$aref;
195 $res = encode_json
($self->$method(@$aref));
197 die "invalid command\n";
201 &$writedata($parent, 'E', $err);
204 &$writedata($parent, '>', $res);
214 my ($self, $new_timeout) = @_;
216 $self->{timeout
} = $new_timeout if $new_timeout;
218 return $self->{timeout
};
225 #print "$$: DESTROY WAIT0\n";
226 &$kill_worker($self);
227 #print "$$: DESTROY WAIT\n";
229 #print "$$: DESTROY SHUTDOWN\n";
230 pve_rados_shutdown
($self->{conn
}) if $self->{conn
};
235 my ($self, @args) = @_;
238 my $data = encode_json
(['cluster_stat', @args]);
239 my $raw = &$sendcmd($self, 'C', $data);
240 return decode_json
($raw);
242 return pve_rados_cluster_stat
($self->{conn
});
246 # example1: { prefix => 'get_command_descriptions'})
247 # example2: { prefix => 'mon dump', format => 'json' }
249 my ($self, $cmd) = @_;
251 $cmd->{format
} = 'json' if !$cmd->{format
};
253 my $json = encode_json
($cmd);
255 my $raw = &$sendcmd($self, 'M', $json);
257 if ($cmd->{format
} && $cmd->{format
} eq 'json') {
258 return length($raw) ? decode_json
($raw) : undef;
269 PVE::RADOS - Perl bindings for librados
275 my $rados = PVE::RADOS::new();
276 my $stat = $rados->cluster_stat();
277 my $res = $rados->mon_command({ prefix => 'mon dump', format => 'json' });
281 Perl bindings for librados.
289 Dietmar Maurer, E<lt>dietmar@proxmox.com<gt>