Skip to content

Port network_forwards to the database generator #2085

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion cmd/incusd/network_allocations.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,25 @@ func networkAllocationsGet(d *Daemon, r *http.Request) response.Response {
var forwards map[int64]*api.NetworkForward

err = d.db.Cluster.Transaction(r.Context(), func(ctx context.Context, tx *db.ClusterTx) error {
forwards, err = tx.GetNetworkForwards(ctx, n.ID(), false)
networkID := int(n.ID())
dbRecords, err := dbCluster.GetNetworkForwards(ctx, tx.Tx(), dbCluster.NetworkForwardFilter{
NetworkID: &networkID,
})
if err != nil {
return err
}

forwards = make(map[int64]*api.NetworkForward)
for _, dbRecord := range dbRecords {
// Change to api format
forwardID := int64(dbRecord.ID)
forward, err := dbRecord.ToAPI(ctx, tx.Tx())
if err != nil {
return err
}

forwards[forwardID] = forward
}

return err
})
Expand Down
98 changes: 92 additions & 6 deletions cmd/incusd/network_forwards.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/lxc/incus/v6/internal/server/auth"
clusterRequest "github.com/lxc/incus/v6/internal/server/cluster/request"
"github.com/lxc/incus/v6/internal/server/db"
dbCluster "github.com/lxc/incus/v6/internal/server/db/cluster"
"github.com/lxc/incus/v6/internal/server/lifecycle"
"github.com/lxc/incus/v6/internal/server/network"
"github.com/lxc/incus/v6/internal/server/project"
Expand Down Expand Up @@ -171,8 +172,6 @@ func networkForwardsGet(d *Daemon, r *http.Request) response.Response {
return response.BadRequest(fmt.Errorf("Network driver %q does not support forwards", n.Type()))
}

memberSpecific := false // Get forwards for all cluster members.

recursion := localUtil.IsRecursionRequest(r)

// Parse filter value.
Expand All @@ -191,7 +190,25 @@ func networkForwardsGet(d *Daemon, r *http.Request) response.Response {
var records map[int64]*api.NetworkForward

err = s.DB.Cluster.Transaction(r.Context(), func(ctx context.Context, tx *db.ClusterTx) error {
records, err = tx.GetNetworkForwards(ctx, n.ID(), memberSpecific)
networkID := int(n.ID())
dbRecords, err := dbCluster.GetNetworkForwards(ctx, tx.Tx(), dbCluster.NetworkForwardFilter{
NetworkID: &networkID,
})
if err != nil {
return err
}

records = make(map[int64]*api.NetworkForward)
for _, dbRecord := range dbRecords {
// Change to api format
forwardID := int64(dbRecord.ID)
forward, err := dbRecord.ToAPI(ctx, tx.Tx())
if err != nil {
return err
}

records[forwardID] = forward
}

return err
})
Expand Down Expand Up @@ -219,7 +236,20 @@ func networkForwardsGet(d *Daemon, r *http.Request) response.Response {
var listenAddresses map[int64]string

err = s.DB.Cluster.Transaction(r.Context(), func(ctx context.Context, tx *db.ClusterTx) error {
listenAddresses, err = tx.GetNetworkForwardListenAddresses(ctx, n.ID(), memberSpecific)
networkID := int(n.ID())
dbRecords, err := dbCluster.GetNetworkForwards(ctx, tx.Tx(), dbCluster.NetworkForwardFilter{
NetworkID: &networkID,
})
if err != nil {
return err
}

listenAddresses = make(map[int64]string)
for _, dbRecord := range dbRecords {
// Get listen address
forwardID := int64(dbRecord.ID)
listenAddresses[forwardID] = dbRecord.ListenAddress
}

return err
})
Expand Down Expand Up @@ -481,7 +511,35 @@ func networkForwardGet(d *Daemon, r *http.Request) response.Response {
var forward *api.NetworkForward

err = s.DB.Cluster.Transaction(r.Context(), func(ctx context.Context, tx *db.ClusterTx) error {
_, forward, err = tx.GetNetworkForward(ctx, n.ID(), memberSpecific, listenAddress)
networkID := int(n.ID())
dbRecords, err := dbCluster.GetNetworkForwards(ctx, tx.Tx(), dbCluster.NetworkForwardFilter{
NetworkID: &networkID,
ListenAddress: &listenAddress,
})
if err != nil {
return err
}

filteredRecords := make([]dbCluster.NetworkForward, 0, len(dbRecords))
for _, dbRecord := range dbRecords {
// Include all records if memberSpecific is turned off
// Otherwise, filter based offed of dbRecords with same node id
if !memberSpecific || (!dbRecord.NodeID.Valid || (dbRecord.NodeID.Int64 == tx.GetNodeID())) {
filteredRecords = append(filteredRecords, dbRecord)
}
}

if len(filteredRecords) == 0 {
return api.StatusErrorf(http.StatusNotFound, "Network forward not found")
}

if len(filteredRecords) > 1 {
return api.StatusErrorf(http.StatusConflict, "Network forward found on more than one cluster member. Please target a specific member")
}

// change to api format
dbNetworkForward := filteredRecords[0]
forward, err = dbNetworkForward.ToAPI(ctx, tx.Tx())

return err
})
Expand Down Expand Up @@ -612,7 +670,35 @@ func networkForwardPut(d *Daemon, r *http.Request) response.Response {
var forward *api.NetworkForward

err = s.DB.Cluster.Transaction(r.Context(), func(ctx context.Context, tx *db.ClusterTx) error {
_, forward, err = tx.GetNetworkForward(ctx, n.ID(), memberSpecific, listenAddress)
networkID := int(n.ID())
dbRecords, err := dbCluster.GetNetworkForwards(ctx, tx.Tx(), dbCluster.NetworkForwardFilter{
NetworkID: &networkID,
ListenAddress: &listenAddress,
})
if err != nil {
return err
}

filteredRecords := make([]dbCluster.NetworkForward, 0, len(dbRecords))
for _, dbRecord := range dbRecords {
// Include all records if memberSpecific is turned off
// Otherwise, filter based offed of dbRecords with same node id
if !memberSpecific || (!dbRecord.NodeID.Valid || (dbRecord.NodeID.Int64 == tx.GetNodeID())) {
filteredRecords = append(filteredRecords, dbRecord)
}
}

if len(filteredRecords) == 0 {
return api.StatusErrorf(http.StatusNotFound, "Network forward not found")
}

if len(filteredRecords) > 1 {
return api.StatusErrorf(http.StatusConflict, "Network forward found on more than one cluster member. Please target a specific member")
}

// change to api format
dbNetworkForward := filteredRecords[0]
forward, err = dbNetworkForward.ToAPI(ctx, tx.Tx())

return err
})
Expand Down
96 changes: 96 additions & 0 deletions internal/server/db/cluster/network_forwards.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
//go:build linux && cgo && !agent

package cluster

import (
"context"
"database/sql"

"github.com/lxc/incus/v6/shared/api"
)

// Code generation directives.
//
//generate-database:mapper target network_forwards.mapper.go
//generate-database:mapper reset -i -b "//go:build linux && cgo && !agent"
//
//generate-database:mapper stmt -e network_forward objects table=networks_forwards
//generate-database:mapper stmt -e network_forward objects-by-NetworkID table=networks_forwards
//generate-database:mapper stmt -e network_forward objects-by-NetworkID-and-ListenAddress table=networks_forwards
//generate-database:mapper stmt -e network_forward create table=networks_forwards
//generate-database:mapper stmt -e network_forward delete-by-NetworkID-and-ID table=networks_forwards
//generate-database:mapper stmt -e network_forward id table=networks_forwards
//generate-database:mapper stmt -e network_forward update table=networks_forwards
//
//generate-database:mapper method -i -e network_forward GetMany references=Config table=networks_forwards
//generate-database:mapper method -i -e network_forward GetOne table=networks_forwards
//generate-database:mapper method -i -e network_forward ID table=networks_forwards
//generate-database:mapper method -i -e network_forward Exists table=networks_forwards
//generate-database:mapper method -i -e network_forward Create references=Config table=networks_forwards
//generate-database:mapper method -i -e network_forward Update references=Config table=networks_forwards
//generate-database:mapper method -i -e network_forward DeleteOne-by-NetworkID-and-ID table=networks_forwards

// NetworkForward is a value object holding db-related details about a network forward.
type NetworkForward struct {
ID int
NetworkID int `db:"primary=yes&column=network_id"`
NodeID sql.NullInt64 `db:"column=node_id&nullable=true"`
Location *string `db:"leftjoin=nodes.name&omit=create,update"`
ListenAddress string `db:"primary=yes"`
Description string
Ports []api.NetworkForwardPort `db:"marshal=json"`
}

// NetworkForwardFilter specifies potential query parameter fields.
type NetworkForwardFilter struct {
ID *int
NetworkID *int
NodeID *int
ListenAddress *string
}

// ToAPI converts the DB records to an API record.
func (n *NetworkForward) ToAPI(ctx context.Context, tx *sql.Tx) (*api.NetworkForward, error) {
// Get the config.
config, err := GetNetworkForwardConfig(ctx, tx, n.ID)
if err != nil {
return nil, err
}

// Fill in the struct.
resp := api.NetworkForward{
NetworkForwardPut: api.NetworkForwardPut{
Description: n.Description,
Config: config,
Ports: n.Ports,
},
ListenAddress: n.ListenAddress,
Location: *n.Location,
}

return &resp, nil
}

// UpdateNetworkForwardAPI updates the description and ports of the network forward.
func UpdateNetworkForwardAPI(ctx context.Context, db tx, curForwardID int64, curNetworkID int, curNodeID sql.NullInt64, curListenAddress string, newForward *api.NetworkForwardPut) error {
newRecord := NetworkForward{
NetworkID: curNetworkID,
NodeID: curNodeID,
ListenAddress: curListenAddress,
Description: newForward.Description,
Ports: newForward.Ports,
}

if newForward.Ports == nil {
newRecord.Ports = []api.NetworkForwardPort{}
}

// Update the network forward
err := UpdateNetworkForward(ctx, db, curNetworkID, curListenAddress, newRecord)
if err != nil {
return err
}

// Update the network forward config
return UpdateNetworkForwardConfig(ctx, db, curForwardID, newForward.Config)
}
48 changes: 48 additions & 0 deletions internal/server/db/cluster/network_forwards.interface.mapper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//go:build linux && cgo && !agent

package cluster

import "context"

// NetworkForwardGenerated is an interface of generated methods for NetworkForward.
type NetworkForwardGenerated interface {
// GetNetworkForwardConfig returns all available NetworkForward Config
// generator: network_forward GetMany
GetNetworkForwardConfig(ctx context.Context, db tx, networkForwardID int, filters ...ConfigFilter) (map[string]string, error)

// GetNetworkForwards returns all available network_forwards.
// generator: network_forward GetMany
GetNetworkForwards(ctx context.Context, db dbtx, filters ...NetworkForwardFilter) ([]NetworkForward, error)

// GetNetworkForward returns the network_forward with the given key.
// generator: network_forward GetOne
GetNetworkForward(ctx context.Context, db dbtx, networkID int, listenAddress string) (*NetworkForward, error)

// GetNetworkForwardID return the ID of the network_forward with the given key.
// generator: network_forward ID
GetNetworkForwardID(ctx context.Context, db tx, networkID int, listenAddress string) (int64, error)

// NetworkForwardExists checks if a network_forward with the given key exists.
// generator: network_forward Exists
NetworkForwardExists(ctx context.Context, db dbtx, networkID int, listenAddress string) (bool, error)

// CreateNetworkForwardConfig adds new network_forward Config to the database.
// generator: network_forward Create
CreateNetworkForwardConfig(ctx context.Context, db dbtx, networkForwardID int64, config map[string]string) error

// CreateNetworkForward adds a new network_forward to the database.
// generator: network_forward Create
CreateNetworkForward(ctx context.Context, db dbtx, object NetworkForward) (int64, error)

// UpdateNetworkForwardConfig updates the network_forward Config matching the given key parameters.
// generator: network_forward Update
UpdateNetworkForwardConfig(ctx context.Context, db tx, networkForwardID int64, config map[string]string) error

// UpdateNetworkForward updates the network_forward matching the given key parameters.
// generator: network_forward Update
UpdateNetworkForward(ctx context.Context, db tx, networkID int, listenAddress string, object NetworkForward) error

// DeleteNetworkForward deletes the network_forward matching the given key parameters.
// generator: network_forward DeleteOne-by-NetworkID-and-ID
DeleteNetworkForward(ctx context.Context, db dbtx, networkID int, id int) error
}
Loading
Loading