Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SCSI ensure filesystem #1757

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions ext4/tar2ext4/tar2ext4.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,19 +215,19 @@ func Convert(r io.Reader, w io.ReadWriteSeeker, options ...Option) error {
// More details can be found here https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout
//
// Our goal is to skip the Group 0 padding, read and return the ext4 SuperBlock
func ReadExt4SuperBlock(vhdPath string) (*format.SuperBlock, error) {
vhd, err := os.OpenFile(vhdPath, os.O_RDONLY, 0)
func ReadExt4SuperBlock(devicePath string) (*format.SuperBlock, error) {
dev, err := os.OpenFile(devicePath, os.O_RDONLY, 0)
if err != nil {
return nil, err
}
defer vhd.Close()
defer dev.Close()

// Skip padding at the start
if _, err := vhd.Seek(1024, io.SeekStart); err != nil {
if _, err := dev.Seek(1024, io.SeekStart); err != nil {
return nil, err
}
var sb format.SuperBlock
if err := binary.Read(vhd, binary.LittleEndian, &sb); err != nil {
if err := binary.Read(dev, binary.LittleEndian, &sb); err != nil {
return nil, err
}
// Make sure the magic bytes are correct.
Expand All @@ -237,6 +237,15 @@ func ReadExt4SuperBlock(vhdPath string) (*format.SuperBlock, error) {
return &sb, nil
}

// IsDeviceExt4 is will read the device's superblock and determine if it is
// and ext4 superblock.
func IsDeviceExt4(devicePath string) bool {
// ReadExt4SuperBlock will check the superblock magic number for us,
// so we know if no error is returned, this is an ext4 device.
_, err := ReadExt4SuperBlock(devicePath)
return err == nil
}

// ConvertAndComputeRootDigest writes a compact ext4 file system image that contains the files in the
// input tar stream, computes the resulting file image's cryptographic hashes (merkle tree) and returns
// merkle tree root digest. Convert is called with minimal options: ConvertWhiteout and MaximumDiskSize
Expand Down
18 changes: 14 additions & 4 deletions internal/guest/runtime/hcsv2/uvm.go
Original file line number Diff line number Diff line change
Expand Up @@ -980,9 +980,14 @@ func modifyMappedVirtualDisk(
return errors.Wrapf(err, "mounting scsi device controller %d lun %d onto %s denied by policy", mvd.Controller, mvd.Lun, mvd.MountPath)
}
}

config := &scsi.Config{
Encrypted: mvd.Encrypted,
VerityInfo: mvd.VerityInfo,
EnsureFilesystem: mvd.EnsureFilesystem,
Filesystem: mvd.Filesystem,
}
return scsi.Mount(mountCtx, mvd.Controller, mvd.Lun, mvd.Partition, mvd.MountPath,
mvd.ReadOnly, mvd.Encrypted, mvd.Options, mvd.VerityInfo)
mvd.ReadOnly, mvd.Options, config)
}
return nil
case guestrequest.RequestTypeRemove:
Expand All @@ -992,9 +997,14 @@ func modifyMappedVirtualDisk(
return fmt.Errorf("unmounting scsi device at %s denied by policy: %w", mvd.MountPath, err)
}
}

config := &scsi.Config{
Encrypted: mvd.Encrypted,
VerityInfo: mvd.VerityInfo,
EnsureFilesystem: mvd.EnsureFilesystem,
Filesystem: mvd.Filesystem,
}
if err := scsi.Unmount(ctx, mvd.Controller, mvd.Lun, mvd.Partition,
mvd.MountPath, mvd.Encrypted, mvd.VerityInfo); err != nil {
mvd.MountPath, config); err != nil {
return err
}
}
Expand Down
22 changes: 2 additions & 20 deletions internal/guest/storage/crypt/crypt.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ var (
_cryptsetupOpen = cryptsetupOpen
_generateKeyFile = generateKeyFile
_osMkdirTemp = os.MkdirTemp
_mkfsXfs = mkfsXfs
_osRemoveAll = os.RemoveAll
_zeroFirstBlock = zeroFirstBlock
)
Expand Down Expand Up @@ -88,17 +87,6 @@ func cryptsetupClose(deviceName string) error {
return cryptsetupCommand(closeArgs)
}

// invoke mkfs.xfs for the given device.
func mkfsXfs(devicePath string) error {
args := []string{"-f", devicePath}
cmd := exec.Command("mkfs.xfs", args...)
output, err := cmd.CombinedOutput()
if err != nil {
return errors.Wrapf(err, "failed to execute mkfs.ext4: %s", string(output))
}
return nil
}

// EncryptDevice creates a dm-crypt target for a container scratch vhd.
//
// In order to mount a block device as an encrypted device:
Expand All @@ -121,12 +109,11 @@ func mkfsXfs(devicePath string) error {
// /dev/mapper/`cryptDeviceTemplate`. This can be mounted directly, but it
// doesn't have any format yet.
//
// 4. Format the unencrypted block device as xfs.
// 4. Prepare the unecrypted block device to be later formatted as xfs
// 4.1. Zero the first block. It appears that mkfs.xfs reads this before formatting.
// 4.2. Format the device as xfs.

func EncryptDevice(ctx context.Context, source string, dmCryptName string) (path string, err error) {
// Create temporary directory to store the keyfile and EXT4 image
// Create temporary directory to store the keyfile and xfs image
tempDir, err := _osMkdirTemp("", "dm-crypt")
if err != nil {
return "", errors.Wrapf(err, "failed to create temporary folder: %s", source)
Expand Down Expand Up @@ -172,11 +159,6 @@ func EncryptDevice(ctx context.Context, source string, dmCryptName string) (path
return "", fmt.Errorf("failed to zero first block: %w", err)
}

// 4.2. Format it as xfs
if err = _mkfsXfs(deviceNamePath); err != nil {
return "", fmt.Errorf("mkfs.xfs failed to format %s: %w", deviceNamePath, err)
}

return deviceNamePath, nil
}

Expand Down
43 changes: 0 additions & 43 deletions internal/guest/storage/crypt/crypt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,46 +125,6 @@ func Test_Encrypt_Cryptsetup_Open_Error(t *testing.T) {
}
}

func Test_Encrypt_Mkfs_Error(t *testing.T) {
clearCryptTestDependencies()

// Test what happens when mkfs fails to format the unencrypted device.
// Verify that the arguments passed to it are the right ones.
_generateKeyFile = func(path string, size int64) error {
return nil
}
_osRemoveAll = func(path string) error {
return nil
}
_cryptsetupFormat = func(source string, keyFilePath string) error {
return nil
}
_cryptsetupOpen = func(source string, deviceName string, keyFilePath string) error {
return nil
}
_cryptsetupClose = func(deviceName string) error {
return nil
}
_zeroFirstBlock = func(_ string, _ int) error {
return nil
}

source := "/dev/sda"
formatTarget := "/dev/mapper/dm-crypt-name"

expectedErr := errors.New("expected error message")
_mkfsXfs = func(arg string) error {
if arg != formatTarget {
t.Fatalf("expected args: '%v' got: '%v'", formatTarget, arg)
}
return expectedErr
}

if _, err := EncryptDevice(context.Background(), source, "dm-crypt-name"); errors.Unwrap(err) != expectedErr {
t.Fatalf("expected err: '%v' got: '%v'", expectedErr, err)
}
}

func Test_Encrypt_Success(t *testing.T) {
clearCryptTestDependencies()

Expand All @@ -184,9 +144,6 @@ func Test_Encrypt_Success(t *testing.T) {
_zeroFirstBlock = func(_ string, _ int) error {
return nil
}
_mkfsXfs = func(arg string) error {
return nil
}

source := "/dev/sda"
dmCryptName := "dm-crypt-name"
Expand Down
2 changes: 1 addition & 1 deletion internal/guest/storage/ext4/format.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func mkfsExt4Command(args []string) error {
}
return nil
}
func FormatExt4(ctx context.Context, source string) error {
func Format(ctx context.Context, source string) error {
// Format source as ext4
if err := mkfsExt4Command([]string{source}); err != nil {
return fmt.Errorf("mkfs.ext4 failed to format %s: %w", source, err)
Expand Down
Loading
Loading