my $print_content = sub {
my ($list) = @_;
- my $maxlenname = 0;
+ my ($maxlenname, $maxsize) = (0, 0);
foreach my $info (@$list) {
-
my $volid = $info->{volid};
my $sidlen = length ($volid);
$maxlenname = $sidlen if $sidlen > $maxlenname;
+ $maxsize = $info->{size} if ($info->{size} // 0) > $maxsize;
}
+ my $sizemaxdigits = length($maxsize);
+
+ my $basefmt = "%-${maxlenname}s %-7s %-9s %${sizemaxdigits}s";
+ printf "$basefmt %s\n", "Volid", "Format", "Type", "Size", "VMID";
foreach my $info (@$list) {
next if !$info->{vmid};
my $volid = $info->{volid};
- printf "%-${maxlenname}s %5s %10d %d\n", $volid,
- $info->{format}, $info->{size}, $info->{vmid};
+ printf "$basefmt %d\n", $volid, $info->{format}, $info->{content}, $info->{size}, $info->{vmid};
}
foreach my $info (sort { $a->{format} cmp $b->{format} } @$list) {
next if $info->{vmid};
my $volid = $info->{volid};
- printf "%-${maxlenname}s %5s %10d\n", $volid,
- $info->{format}, $info->{size};
+ printf "$basefmt\n", $volid, $info->{format}, $info->{content}, $info->{size};
}
};
enum => $KNOWN_EXPORT_FORMATS,
},
filename => {
- description => "Source file name",
+ description => "Source file name. For '-' stdin is used, the " .
+ "tcp://<IP-or-CIDR> format allows to use a TCP connection as input. " .
+ "Else, the file is treated as common file.",
type => 'string',
},
base => {
my $infh;
if ($filename eq '-') {
$infh = \*STDIN;
+ } elsif ($filename =~ m!^tcp://(([^/]+)(/\d+)?)$!) {
+ my ($cidr, $ip, $subnet) = ($1, $2, $3);
+ if ($subnet) { # got real CIDR notation, not just IP
+ my $ips = PVE::Network::get_local_ip_from_cidr($cidr);
+ die "Unable to get any local IP address in network '$cidr'\n"
+ if scalar(@$ips) < 1;
+ die "Got multiple local IP address in network '$cidr'\n"
+ if scalar(@$ips) > 1;
+
+ $ip = $ips->[0];
+ }
+ my $family = PVE::Tools::get_host_address_family($ip);
+ my $port = PVE::Tools::next_migrate_port($family, $ip);
+
+ my $sock_params = {
+ Listen => 1,
+ ReuseAddr => 1,
+ Proto => &Socket::IPPROTO_TCP,
+ GetAddrInfoFlags => 0,
+ LocalAddr => $ip,
+ LocalPort => $port,
+ };
+ my $socket = IO::Socket::IP->new(%$sock_params)
+ or die "failed to open socket: $!\n";
+
+ print "$ip\n$port\n"; # tell remote where to connect
+ *STDOUT->flush();
+
+ my $prev_alarm = alarm 0;
+ local $SIG{ALRM} = sub { die "timed out waiting for client\n" };
+ alarm 30;
+ my $client = $socket->accept; # Wait for a client
+ alarm $prev_alarm;
+ close($socket);
+
+ $infh = \*$client;
} else {
sysopen($infh, $filename, O_RDONLY)
or die "open($filename): $!\n";
type => 'array',
items => {
type => "object",
- properties => {
+ properties => {
volname => {
description => "The volume name.",
type => 'string',
}],
free => [ "PVE::API2::Storage::Content", 'delete', ['volume'],
{ node => $nodename } ],
- nfsscan => [ __PACKAGE__, 'nfsscan', ['server'],
- { node => $nodename }, sub {
- my $res = shift;
-
- my $maxlen = 0;
- foreach my $rec (@$res) {
- my $len = length ($rec->{path});
- $maxlen = $len if $len > $maxlen;
- }
- foreach my $rec (@$res) {
- printf "%-${maxlen}s %s\n", $rec->{path}, $rec->{options};
- }
- }],
- cifsscan => [ __PACKAGE__, 'cifsscan', ['server'],
- { node => $nodename }, sub {
- my $res = shift;
-
- my $maxlen = 0;
- foreach my $rec (@$res) {
- my $len = length ($rec->{share});
- $maxlen = $len if $len > $maxlen;
- }
- foreach my $rec (@$res) {
- printf "%-${maxlen}s %s\n", $rec->{share}, $rec->{description};
- }
- }],
- glusterfsscan => [ __PACKAGE__, 'glusterfsscan', ['server'],
- { node => $nodename }, sub {
- my $res = shift;
-
- foreach my $rec (@$res) {
- printf "%s\n", $rec->{volname};
- }
- }],
- iscsiscan => [ __PACKAGE__, 'iscsiscan', ['portal'],
- { node => $nodename }, sub {
- my $res = shift;
-
- my $maxlen = 0;
- foreach my $rec (@$res) {
- my $len = length ($rec->{target});
- $maxlen = $len if $len > $maxlen;
- }
- foreach my $rec (@$res) {
- printf "%-${maxlen}s %s\n", $rec->{target}, $rec->{portal};
- }
- }],
- lvmscan => [ __PACKAGE__, 'lvmscan', [],
- { node => $nodename }, sub {
- my $res = shift;
- foreach my $rec (@$res) {
- printf "$rec->{vg}\n";
- }
- }],
- lvmthinscan => [ __PACKAGE__, 'lvmthinscan', ['vg'],
- { node => $nodename }, sub {
- my $res = shift;
- foreach my $rec (@$res) {
- printf "$rec->{lv}\n";
- }
- }],
- zfsscan => [ __PACKAGE__, 'zfsscan', [],
- { node => $nodename }, sub {
- my $res = shift;
-
- foreach my $rec (@$res) {
- printf "$rec->{pool}\n";
- }
- }],
+ scan => {
+ nfs => [ __PACKAGE__, 'nfsscan', ['server'], { node => $nodename }, sub {
+ my $res = shift;
+
+ my $maxlen = 0;
+ foreach my $rec (@$res) {
+ my $len = length ($rec->{path});
+ $maxlen = $len if $len > $maxlen;
+ }
+ foreach my $rec (@$res) {
+ printf "%-${maxlen}s %s\n", $rec->{path}, $rec->{options};
+ }
+ }],
+ cifs => [ __PACKAGE__, 'cifsscan', ['server'], { node => $nodename }, sub {
+ my $res = shift;
+
+ my $maxlen = 0;
+ foreach my $rec (@$res) {
+ my $len = length ($rec->{share});
+ $maxlen = $len if $len > $maxlen;
+ }
+ foreach my $rec (@$res) {
+ printf "%-${maxlen}s %s\n", $rec->{share}, $rec->{description};
+ }
+ }],
+ glusterfs => [ __PACKAGE__, 'glusterfsscan', ['server'], { node => $nodename }, sub {
+ my $res = shift;
+
+ foreach my $rec (@$res) {
+ printf "%s\n", $rec->{volname};
+ }
+ }],
+ iscsi => [ __PACKAGE__, 'iscsiscan', ['portal'], { node => $nodename }, sub {
+ my $res = shift;
+
+ my $maxlen = 0;
+ foreach my $rec (@$res) {
+ my $len = length ($rec->{target});
+ $maxlen = $len if $len > $maxlen;
+ }
+ foreach my $rec (@$res) {
+ printf "%-${maxlen}s %s\n", $rec->{target}, $rec->{portal};
+ }
+ }],
+ lvm => [ __PACKAGE__, 'lvmscan', [], { node => $nodename }, sub {
+ my $res = shift;
+ foreach my $rec (@$res) {
+ printf "$rec->{vg}\n";
+ }
+ }],
+ lvmthin => [ __PACKAGE__, 'lvmthinscan', ['vg'], { node => $nodename }, sub {
+ my $res = shift;
+ foreach my $rec (@$res) {
+ printf "$rec->{lv}\n";
+ }
+ }],
+ zfs => [ __PACKAGE__, 'zfsscan', [], { node => $nodename }, sub {
+ my $res = shift;
+
+ foreach my $rec (@$res) {
+ printf "$rec->{pool}\n";
+ }
+ }],
+ },
+ nfsscan => { alias => 'scan nfs' },
+ cifsscan => { alias => 'scan cifs' },
+ glusterfsscan => { alias => 'scan glusterfs' },
+ iscsiscan => { alias => 'scan iscsi' },
+ lvmscan => { alias => 'scan lvm' },
+ lvmthinscan => { alias => 'scan lvmthin' },
+ zfsscan => { alias => 'scan zfs' },
path => [ __PACKAGE__, 'path', ['volume']],
extractconfig => [__PACKAGE__, 'extractconfig', ['volume']],
export => [ __PACKAGE__, 'export', ['volume', 'format', 'filename']],