Skip to content

Commit 630c996

Browse files
Palace Automation Botclaude
andcommitted
Fix issue #52: LXC resize and creation with mfsbdev
This commit fixes two critical issues with LXC containers on mfsbdev storage: 1. LXC creation failure: "Device size reported to be zero" - Root cause: mfsbdev map creates a 0-byte file, causing mkfs.ext4 to fail - Solution: Added truncate command in alloc_image() to set correct file size - This allows LXC to mkfs the file directly for rootfs creation 2. LXC resize failure: "can't resize this image format" - Fixed volume_resize() with proper path handling - Added mfsnbdlink socket support for multi-cluster deployments - Implemented proper .size file updates after resize 3. Added get_mfsbdev_size() helper function - Queries actual volume size from mfsbdev daemon - Parses 'mfsbdev list' output for accurate size reporting - Supports custom NBD socket paths via mfsnbdlink Tested successfully on moosefs-storage: - LXC creation: ✅ 2GB rootfs created correctly - LXC resize: ✅ 2GB → 4GB resize works perfectly 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 2caa3a3 commit 630c996

File tree

1 file changed

+82
-6
lines changed

1 file changed

+82
-6
lines changed

MooseFSPlugin.pm

Lines changed: 82 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,31 @@ sub alloc_image {
474474
die $@;
475475
}
476476

477+
# Create the actual image file for LXC compatibility
478+
# LXC needs to mkfs the file directly, not through NBD
479+
# mfsbdev map creates a 0-byte file, we need to set the correct size
480+
my $full_path = "$scfg->{path}$path";
481+
my $current_size = -s $full_path || 0;
482+
483+
if ($current_size != $size_bytes) {
484+
log_debug "[alloc_image] Setting file size for LXC compatibility: $full_path ($current_size -> $size_bytes bytes)";
485+
eval {
486+
run_command(['truncate', '-s', $size_bytes, $full_path],
487+
errmsg => "Failed to set image file size");
488+
};
489+
if ($@) {
490+
log_debug "[alloc_image] Failed to set file size: $@";
491+
# Try to unmap on failure
492+
eval {
493+
my $unmap_cmd = $scfg->{mfsnbdlink}
494+
? ['/usr/sbin/mfsbdev', 'unmap', '-l', $scfg->{mfsnbdlink}, '-f', $path]
495+
: ['/usr/sbin/mfsbdev', 'unmap', '-f', $path];
496+
run_command($unmap_cmd);
497+
};
498+
die $@;
499+
}
500+
}
501+
477502
return "$vmid/$name";
478503
}
479504

@@ -882,13 +907,46 @@ sub filesystem_path {
882907
return "$scfg->{path}$path";
883908
}
884909

910+
# Query mfsbdev for volume size by parsing 'mfsbdev list' output
911+
sub get_mfsbdev_size {
912+
my ($class, $scfg, $mfs_path) = @_;
913+
914+
return undef unless moosefs_bdev_is_active($scfg);
915+
916+
my $list_cmd = $scfg->{mfsnbdlink}
917+
? ['/usr/sbin/mfsbdev', 'list', '-l', $scfg->{mfsnbdlink}]
918+
: ['/usr/sbin/mfsbdev', 'list'];
919+
920+
my $list_output = '';
921+
eval {
922+
run_command($list_cmd, outfunc => sub { $list_output .= shift; });
923+
};
924+
return undef if $@;
925+
926+
# Parse mfsbdev list output
927+
# Format: file: /images/204/vm-204-disk-0 ; device: /dev/nbd2 ; link: ... ; size: 2147483648 (2.000GiB) ; ...
928+
for my $line (split /\r?\n/, $list_output) {
929+
if ($line =~ /\bfile:\s*\Q$mfs_path\E\b.*?\bsize:\s*(\d+)/) {
930+
my $size_bytes = $1;
931+
my $size_kib = int($size_bytes / 1024);
932+
log_debug "[get_mfsbdev_size] Found $mfs_path: $size_bytes bytes ($size_kib KiB)";
933+
return $size_kib;
934+
}
935+
}
936+
937+
log_debug "[get_mfsbdev_size] Volume $mfs_path not found in mfsbdev list";
938+
return undef;
939+
}
940+
885941
sub volume_resize {
886942
my ($class, $scfg, $storeid, $volname, $size, $running) = @_;
887943

888944
unless (defined $volname && !ref($volname)) {
889945
Carp::confess("[${\__PACKAGE__}::$0] called with invalid volname: " . (defined $volname ? ref($volname) : 'undef'));
890946
}
891947

948+
log_debug "[volume_resize] Resizing $volname to $size KiB";
949+
892950
# Defensive - make sure $scfg is a hashref, not a storeid
893951
$scfg = PVE::Storage::config()->{ids}->{$storeid} unless ref($scfg) eq 'HASH';
894952

@@ -897,15 +955,33 @@ sub volume_resize {
897955
my ($vtype, $name, $vmid) = $class->parse_volname($volname);
898956
return $class->SUPER::volume_resize(@_) if $vtype ne 'images';
899957

900-
my $path = "/images/$vmid/$name";
958+
my $mfs_path = "/images/$vmid/$name";
959+
my $full_path = "$scfg->{path}$mfs_path";
960+
my $size_file = "$full_path.size";
901961

902-
if (-e $path) {
903-
my $cmd = ['/usr/sbin/mfsbdev', 'resize', $path, $size];
904-
run_command($cmd, errmsg => 'mfsbdev resize failed');
905-
} else {
906-
die "volume '$volname' does not exist\n";
962+
# Check if image exists
963+
if (!-e $full_path) {
964+
die "volume '$volname' does not exist at $full_path\n";
907965
}
908966

967+
log_debug "[volume_resize] Resizing mfsbdev volume: $mfs_path";
968+
969+
# Resize using mfsbdev
970+
my $size_bytes = $size * 1024; # Convert KiB to bytes
971+
my $cmd = $scfg->{mfsnbdlink}
972+
? ['/usr/sbin/mfsbdev', 'resize', '-l', $scfg->{mfsnbdlink}, '-f', $mfs_path, '-s', $size_bytes]
973+
: ['/usr/sbin/mfsbdev', 'resize', '-f', $mfs_path, '-s', $size_bytes];
974+
975+
run_command($cmd, errmsg => 'mfsbdev resize failed');
976+
977+
# Update .size file
978+
log_debug "[volume_resize] Updating .size file to $size KiB";
979+
open(my $fh, '>', $size_file) or die "Failed to write $size_file: $!";
980+
print $fh $size;
981+
close $fh;
982+
983+
log_debug "[volume_resize] Successfully resized $volname to $size KiB";
984+
909985
return undef;
910986
}
911987

0 commit comments

Comments
 (0)