diff --git a/internal/server/network/network_utils.go b/internal/server/network/network_utils.go index 3a9a283e919..1054d32325a 100644 --- a/internal/server/network/network_utils.go +++ b/internal/server/network/network_utils.go @@ -79,30 +79,47 @@ func MACDevName(mac net.HardwareAddr) string { // UsedByInstanceDevices looks for instance NIC devices using the network and runs the supplied usageFunc for each. // Accepts optional filter arguments to specify a subset of instances. func UsedByInstanceDevices(s *state.State, networkProjectName string, networkName string, networkType string, usageFunc func(inst db.InstanceArgs, nicName string, nicConfig map[string]string) error, filters ...cluster.InstanceFilter) error { - return s.DB.Cluster.Transaction(context.TODO(), func(ctx context.Context, tx *db.ClusterTx) error { + // Get the instances. + projects := map[string]api.Project{} + instances := []db.InstanceArgs{} + + err := s.DB.Cluster.Transaction(context.TODO(), func(ctx context.Context, tx *db.ClusterTx) error { return tx.InstanceList(ctx, func(inst db.InstanceArgs, p api.Project) error { - // Get the instance's effective network project name. - instNetworkProject := project.NetworkProjectFromRecord(&p) + projects[inst.Project] = p + instances = append(instances, inst) - // Skip instances who's effective network project doesn't match this Network's project. - if instNetworkProject != networkProjectName { - return nil - } + return nil + }, filters...) + }) + if err != nil { + return err + } - // Look for NIC devices using this network. - devices := db.ExpandInstanceDevices(inst.Devices.Clone(), inst.Profiles) - for devName, devConfig := range devices { - if isInUseByDevice(networkName, networkType, devConfig) { - err := usageFunc(inst, devName, devConfig) - if err != nil { - return err - } + // Go through the instances and run usageFunc. + for _, inst := range instances { + p := projects[inst.Project] + + // Get the instance's effective network project name. + instNetworkProject := project.NetworkProjectFromRecord(&p) + + // Skip instances who's effective network project doesn't match this Network's project. + if instNetworkProject != networkProjectName { + return nil + } + + // Look for NIC devices using this network. + devices := db.ExpandInstanceDevices(inst.Devices.Clone(), inst.Profiles) + for devName, devConfig := range devices { + if isInUseByDevice(networkName, networkType, devConfig) { + err := usageFunc(inst, devName, devConfig) + if err != nil { + return err } } + } + } - return nil - }, filters...) - }) + return nil } // UsedBy returns list of API resources using network. Accepts firstOnly argument to indicate that only the first