diff --git a/lxd/network/driver_ovn.go b/lxd/network/driver_ovn.go index ddd631637163..c42a8e0ce815 100644 --- a/lxd/network/driver_ovn.go +++ b/lxd/network/driver_ovn.go @@ -2020,59 +2020,11 @@ func (n *ovn) Create(clientType request.ClientType) error { return nil } -// allowedUplinkNetworks returns a list of allowed networks to use as uplinks based on project restrictions. -func (n *ovn) allowedUplinkNetworks(p *api.Project) ([]string, error) { - var uplinkNetworkNames []string - - err := n.state.DB.Cluster.Transaction(context.TODO(), func(ctx context.Context, tx *db.ClusterTx) error { - // Uplink networks are always from the default project. - networks, err := tx.GetCreatedNetworksByProject(ctx, api.ProjectDefaultName) - if err != nil { - return fmt.Errorf("Failed getting uplink networks: %w", err) - } - - // Add any compatible networks to the uplink network list. - for _, network := range networks { - if network.Type == "bridge" || network.Type == "physical" { - uplinkNetworkNames = append(uplinkNetworkNames, network.Name) - } - } - - return nil - }) - if err != nil { - return nil, err - } - - // If project is not restricted, return full network list. - if shared.IsFalseOrEmpty(p.Config["restricted"]) { - return uplinkNetworkNames, nil - } - - allowedUplinkNetworkNames := []string{} - - // There are no allowed networks if restricted.networks.uplinks is not set. - if p.Config["restricted.networks.uplinks"] == "" { - return allowedUplinkNetworkNames, nil - } - - // Parse the allowed uplinks and return any that are present in the actual defined networks. - allowedRestrictedUplinks := shared.SplitNTrimSpace(p.Config["restricted.networks.uplinks"], ",", -1, false) - - for _, allowedRestrictedUplink := range allowedRestrictedUplinks { - if shared.ValueInSlice(allowedRestrictedUplink, uplinkNetworkNames) { - allowedUplinkNetworkNames = append(allowedUplinkNetworkNames, allowedRestrictedUplink) - } - } - - return allowedUplinkNetworkNames, nil -} - // validateUplinkNetwork checks if uplink network is allowed, and if empty string is supplied then tries to select // an uplink network from the allowedUplinkNetworks() list if there is only one allowed network. // Returns chosen uplink network name to use. func (n *ovn) validateUplinkNetwork(p *api.Project, uplinkNetworkName string) (string, error) { - allowedUplinkNetworks, err := n.allowedUplinkNetworks(p) + allowedUplinkNetworks, err := AllowedUplinkNetworks(n.state, p.Config) if err != nil { return "", err } diff --git a/lxd/network/network_utils.go b/lxd/network/network_utils.go index 8b8e5ae61657..1360826691c6 100644 --- a/lxd/network/network_utils.go +++ b/lxd/network/network_utils.go @@ -1458,3 +1458,51 @@ func ProxyParseAddr(data string) (*deviceConfig.ProxyAddress, error) { return newProxyAddr, nil } + +// AllowedUplinkNetworks returns a list of allowed networks to use as uplinks based on project restrictions. +func AllowedUplinkNetworks(s *state.State, projectConfig map[string]string) ([]string, error) { + var uplinkNetworkNames []string + + // There are no allowed networks if project is restricted and restricted.networks.uplinks is not set. + if shared.IsTrue(projectConfig["restricted"]) && projectConfig["restricted.networks.uplinks"] == "" { + return []string{}, nil + } + + err := s.DB.Cluster.Transaction(s.ShutdownCtx, func(ctx context.Context, tx *db.ClusterTx) error { + // Uplink networks are always from the default project. + networks, err := tx.GetCreatedNetworksByProject(ctx, api.ProjectDefaultName) + if err != nil { + return fmt.Errorf("Failed getting uplink networks: %w", err) + } + + // Add any compatible networks to the uplink network list. + for _, network := range networks { + if network.Type == "bridge" || network.Type == "physical" { + uplinkNetworkNames = append(uplinkNetworkNames, network.Name) + } + } + + return nil + }) + if err != nil { + return nil, err + } + + // If project is not restricted, return full network list. + if shared.IsFalseOrEmpty(projectConfig["restricted"]) { + return uplinkNetworkNames, nil + } + + allowedUplinkNetworkNames := []string{} + + // Parse the allowed uplinks and return any that are present in the actual defined networks. + allowedRestrictedUplinks := shared.SplitNTrimSpace(projectConfig["restricted.networks.uplinks"], ",", -1, false) + + for _, allowedRestrictedUplink := range allowedRestrictedUplinks { + if shared.ValueInSlice(allowedRestrictedUplink, uplinkNetworkNames) { + allowedUplinkNetworkNames = append(allowedUplinkNetworkNames, allowedRestrictedUplink) + } + } + + return allowedUplinkNetworkNames, nil +} diff --git a/lxd/project/limits/permissions.go b/lxd/project/limits/permissions.go index b88d2fb9a9ec..e809c62f57c1 100644 --- a/lxd/project/limits/permissions.go +++ b/lxd/project/limits/permissions.go @@ -470,9 +470,10 @@ func checkAggregateLimits(info *projectInfo, aggregateKeys []string) error { // parseHostIDMapRange parse the supplied list of host ID map ranges into a idmap.IdmapEntry slice. func parseHostIDMapRange(isUID bool, isGID bool, listValue string) ([]idmap.IdmapEntry, error) { - var idmaps []idmap.IdmapEntry + mapRanges := shared.SplitNTrimSpace(listValue, ",", -1, true) + idmaps := make([]idmap.IdmapEntry, 0, len(mapRanges)) - for _, listItem := range shared.SplitNTrimSpace(listValue, ",", -1, true) { + for _, listItem := range mapRanges { rangeStart, rangeSize, err := validate.ParseUint32Range(listItem) if err != nil { return nil, err