diff --git a/internal/server/device/device_load.go b/internal/server/device/device_load.go index 3169e3c79ba..1b79ff3e928 100644 --- a/internal/server/device/device_load.go +++ b/internal/server/device/device_load.go @@ -153,6 +153,17 @@ func Validate(instConfig instance.ConfigReader, state *state.State, name string, return dev.validateConfig(instConfig) } +// Register performs a lightweight load of the device, bypassing most +// validation to very quickly register the device on server startup. +func Register(inst instance.Instance, s *state.State, name string, conf deviceConfig.Device) error { + dev, err := load(inst, s, inst.Project().Name, name, conf, nil, nil) + if err != nil { + return err + } + + return dev.Register() +} + // LoadByType loads a device by type based on its project and config. // It does not validate config beyond the type fields. func LoadByType(state *state.State, projectName string, conf deviceConfig.Device) (Type, error) { diff --git a/internal/server/device/disk.go b/internal/server/device/disk.go index 7c1870b8e3d..4d6e54d899b 100644 --- a/internal/server/device/disk.go +++ b/internal/server/device/disk.go @@ -738,12 +738,13 @@ func (d *disk) UpdatableFields(oldDevice Type) []string { func (d *disk) Register() error { d.logger.Debug("Initialising mounted disk ref counter") - if d.config["path"] == "/" { - pool, err := storagePools.LoadByInstance(d.state, d.inst) - if err != nil { - return err - } + // Load the pool. + pool, err := storagePools.LoadByInstance(d.state, d.inst) + if err != nil { + return err + } + if d.config["path"] == "/" { // Try to mount the volume that should already be mounted to reinitialize the ref counter. _, err = pool.MountInstance(d.inst, nil) if err != nil { @@ -760,7 +761,7 @@ func (d *disk) Register() error { volName := volFields[0] // Try to mount the volume that should already be mounted to reinitialize the ref counter. - _, err = d.pool.MountCustomVolume(storageProjectName, volName, nil) + _, err = pool.MountCustomVolume(storageProjectName, volName, nil) if err != nil { return err } diff --git a/internal/server/device/nic_bridged.go b/internal/server/device/nic_bridged.go index 3caaa4f5b43..562492a1117 100644 --- a/internal/server/device/nic_bridged.go +++ b/internal/server/device/nic_bridged.go @@ -1751,7 +1751,19 @@ func (d *nicBridged) getHostMTU() (int, error) { // Register sets up anything needed on startup. func (d *nicBridged) Register() error { - err := bgpAddPrefix(&d.deviceCommon, d.network, d.config) + // Skip when not using a managed network. + if d.config["network"] == "" { + return nil + } + + // Load managed network. api.ProjectDefaultName is used here as bridge networks don't support projects. + n, err := network.LoadByName(d.state, api.ProjectDefaultName, d.config["network"]) + if err != nil { + return fmt.Errorf("Error loading network config for %q: %w", d.config["network"], err) + } + + // Add BGP prefix. + err = bgpAddPrefix(&d.deviceCommon, n, d.config) if err != nil { return err } diff --git a/internal/server/device/nic_ovn.go b/internal/server/device/nic_ovn.go index c9340b949c3..ea4e9fd30ca 100644 --- a/internal/server/device/nic_ovn.go +++ b/internal/server/device/nic_ovn.go @@ -1152,7 +1152,24 @@ func (d *nicOVN) State() (*api.InstanceStateNetwork, error) { // Register sets up anything needed on startup. func (d *nicOVN) Register() error { - err := bgpAddPrefix(&d.deviceCommon, d.network, d.config) + // Skip when not using a managed network. + if d.config["network"] == "" { + return nil + } + + // The NIC's network may be a non-default project, so lookup project and get network's project name. + networkProjectName, _, err := project.NetworkProject(d.state.DB.Cluster, d.inst.Project().Name) + if err != nil { + return fmt.Errorf("Failed loading network project name: %w", err) + } + + // Lookup network settings and apply them to the device's config. + n, err := network.LoadByName(d.state, networkProjectName, d.config["network"]) + if err != nil { + return fmt.Errorf("Error loading network config for %q: %w", d.config["network"], err) + } + + err = bgpAddPrefix(&d.deviceCommon, n, d.config) if err != nil { return err } diff --git a/internal/server/instance/drivers/driver_common.go b/internal/server/instance/drivers/driver_common.go index 5b7474dbf0c..712c3488363 100644 --- a/internal/server/instance/drivers/driver_common.go +++ b/internal/server/instance/drivers/driver_common.go @@ -1283,19 +1283,12 @@ func (d *common) devicesAdd(inst instance.Instance, instanceRunning bool) (rever // devicesRegister calls the Register() function on all of the instance's devices. func (d *common) devicesRegister(inst instance.Instance) { for _, entry := range d.ExpandedDevices().Sorted() { - dev, err := d.deviceLoad(inst, entry.Name, entry.Config) + err := device.Register(inst, d.state, entry.Name, entry.Config) if err != nil { if errors.Is(err, device.ErrUnsupportedDevType) { continue // Skip unsupported device (allows for mixed instance type profiles). } - d.logger.Error("Failed register validation for device", logger.Ctx{"err": err, "device": entry.Name}) - continue - } - - // Check whether device wants to register for any events. - err = dev.Register() - if err != nil { d.logger.Error("Failed to register device", logger.Ctx{"err": err, "device": entry.Name}) continue }