Documentation
¶
Overview ¶
Package weftdriverplugin is the wire contract that lets weft run its hypervisor/network/volume/image drivers as external go-plugin processes instead of linking them in-process.
Why this exists: the Apple-VZ driver (weft-driver-vz) binds macOS frameworks via cgo, which forced the whole weft binary to be CGO_ENABLED=1 on darwin. Moving every driver behind a gRPC go-plugin boundary keeps the weft core pure-Go (CGO_ENABLED=0 on every platform); the cgo lives only in the weft-driver-vz plugin executable, and the virtualization entitlement applies to that binary alone.
Shape:
- The four driver interfaces in github.com/openweft/weft-drivers each map to one gRPC service in driverpb (one RPC per method). They were designed flat + context-aware + sentinel-error'd for exactly this — see that package's doc.go.
- One plugin process per host serves all four services on a single connection (BundlePlugin). The host dispenses a *DriverSet of client stubs that satisfy the drivers.* interfaces, so nothing above the HostHandle/DriverHandles boundary changes.
- Host side: Launch() locates + starts the plugin and returns the set. Plugin side: a tiny main calls Serve() with its concrete bundle.
The public-contract sentinels (drivers.ErrNotApplicable / ErrUnsupported / ErrNotFound) and context cancellation survive the boundary as gRPC status codes, reconstructed host-side so errors.Is keeps working (see convert.go).
Index ¶
Constants ¶
const ( EnvHostUUID = "WEFT_DRIVER_HOST_UUID" EnvHostname = "WEFT_DRIVER_HOSTNAME" EnvAZ = "WEFT_DRIVER_AZ" EnvStateDir = "WEFT_DRIVER_STATE_DIR" )
Launch-time configuration is passed to the plugin process via these env vars (read in the plugin's main before it constructs its driver bundle). They're launch-static, so env beats an Init RPC.
const EnvPluginDir = "WEFT_PLUGIN_DIR"
EnvPluginDir names an extra directory to search for plugin executables.
const PluginName = "weft_driver"
PluginName is the dispense key shared by host and plugin.
Variables ¶
var Handshake = plugin.HandshakeConfig{
ProtocolVersion: 1,
MagicCookieKey: "WEFT_DRIVER_PLUGIN",
MagicCookieValue: "f0b9c1e2-weft-driver-grpc",
}
Handshake gates host/plugin compatibility. A mismatched magic cookie makes the plugin refuse to talk (and print a human hint when run directly); ProtocolVersion bumps whenever the driverpb contract changes incompatibly.
Functions ¶
Types ¶
type BundlePlugin ¶
type BundlePlugin struct {
plugin.NetRPCUnsupportedPlugin
Impl *DriverSet
}
BundlePlugin is the go-plugin adapter. On the plugin side Impl carries the concrete drivers; on the host side it's nil and GRPCClient builds stubs.
func (*BundlePlugin) GRPCClient ¶
func (p *BundlePlugin) GRPCClient(_ context.Context, _ *plugin.GRPCBroker, c *grpc.ClientConn) (interface{}, error)
GRPCClient builds the four client stubs over the single shared connection and returns them as a *DriverSet.
func (*BundlePlugin) GRPCServer ¶
func (p *BundlePlugin) GRPCServer(_ *plugin.GRPCBroker, s *grpc.Server) error
GRPCServer registers all four services on the plugin's gRPC server.
type DriverSet ¶
type DriverSet struct {
Hypervisor drivers.HypervisorDriver
Network drivers.NetworkDriver
Volume drivers.VolumeDriver
Image drivers.ImageDriver
}
DriverSet is the dispensed bundle: the four driver interfaces backed by one plugin process. The host maps this onto its own HostHandle/DriverHandles.
type LaunchOptions ¶
type LaunchOptions struct {
// Executable is the plugin binary name (e.g. "weft-driver-vz") resolved
// via SearchDirs / $WEFT_PLUGIN_DIR / the weft binary's dir / $PATH, OR an
// absolute path used as-is.
Executable string
// SearchDirs are checked before $WEFT_PLUGIN_DIR and the weft binary dir.
SearchDirs []string
// Host context handed to the plugin via env so it can build its bundle.
HostUUID string
Hostname string
AZ string
StateDir string
// Logger receives go-plugin + plugin-stderr lines. nil → a Warn-level
// stderr logger (keeps normal runs quiet).
Logger hclog.Logger
}
LaunchOptions configures a single plugin launch.
