treewide: port everything to blockdev

This gets rid of most ad-hoc block device code, using blockdev for
everything. It also gets rid of diskfs for everything but tests. This
enables Metropolis to be installed on non-512-byte block sizes.

Change-Id: I644b5b68bb7bed8106585df3179674789031687a
Reviewed-on: https://review.monogon.dev/c/monogon/+/1873
Tested-by: Jenkins CI
Reviewed-by: Serge Bazanski <serge@monogon.tech>
diff --git a/cloud/agent/BUILD.bazel b/cloud/agent/BUILD.bazel
index e8b4ffd..793f15b 100644
--- a/cloud/agent/BUILD.bazel
+++ b/cloud/agent/BUILD.bazel
@@ -18,6 +18,7 @@
         "//metropolis/node/build/mkimage/osimage",
         "//metropolis/node/core/devmgr",
         "//metropolis/node/core/network",
+        "//metropolis/pkg/blockdev",
         "//metropolis/pkg/bootparam",
         "//metropolis/pkg/efivarfs",
         "//metropolis/pkg/logtree",
diff --git a/cloud/agent/install.go b/cloud/agent/install.go
index a1aec0d..3468cc9 100644
--- a/cloud/agent/install.go
+++ b/cloud/agent/install.go
@@ -5,6 +5,7 @@
 	"bytes"
 	"errors"
 	"fmt"
+	"io/fs"
 	"net/http"
 	"path/filepath"
 
@@ -13,11 +14,27 @@
 
 	bpb "source.monogon.dev/cloud/bmaas/server/api"
 	"source.monogon.dev/metropolis/node/build/mkimage/osimage"
+	"source.monogon.dev/metropolis/pkg/blockdev"
 	"source.monogon.dev/metropolis/pkg/efivarfs"
 	"source.monogon.dev/metropolis/pkg/logtree"
 	npb "source.monogon.dev/net/proto"
 )
 
+// FileSizedReader is a small adapter from fs.File to fs.SizedReader
+// Panics on Stat() failure, so should only be used with sources where Stat()
+// cannot fail.
+type FileSizedReader struct {
+	fs.File
+}
+
+func (f FileSizedReader) Size() int64 {
+	stat, err := f.Stat()
+	if err != nil {
+		panic(err)
+	}
+	return stat.Size()
+}
+
 // install dispatches OSInstallationRequests to the appropriate installer
 // method
 func install(req *bpb.OSInstallationRequest, netConfig *npb.Net, l logtree.LeveledLogger, isEFIBoot bool) error {
@@ -104,6 +121,11 @@
 		return fmt.Errorf("failed marshaling: %w", err)
 	}
 
+	rootDev, err := blockdev.Open(filepath.Join("/dev", req.RootDevice))
+	if err != nil {
+		return fmt.Errorf("failed to open root device: %w", err)
+	}
+
 	installParams := osimage.Params{
 		PartitionSize: osimage.PartitionSizeInfo{
 			ESP:    128,
@@ -111,9 +133,9 @@
 			Data:   128,
 		},
 		SystemImage:    systemImage,
-		EFIPayload:     efiPayload,
+		EFIPayload:     FileSizedReader{efiPayload},
 		NodeParameters: bytes.NewReader(nodeParamsRaw),
-		OutputPath:     filepath.Join("/dev", req.RootDevice),
+		Output:         rootDev,
 	}
 
 	be, err := osimage.Create(&installParams)