Skip to content

Commit

Permalink
Merge pull request #1070 from SpiffyEight77/feat/isolated-ovn-networks
Browse files Browse the repository at this point in the history
Allow creating isolated OVN networks (no uplink)
  • Loading branch information
stgraber authored Aug 9, 2024
2 parents 42e4328 + 86b4da1 commit 8be6b15
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 83 deletions.
4 changes: 4 additions & 0 deletions cmd/incusd/networks.go
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,10 @@ func networksPost(d *Daemon, r *http.Request) response.Response {
return response.BadRequest(fmt.Errorf("No name provided"))
}

if req.Name == "none" {
return response.BadRequest(fmt.Errorf("Network name 'none' is not valid"))
}

// Check if project allows access to network.
if !project.NetworkAllowed(reqProject.Config, req.Name, true) {
return response.SmartError(api.StatusErrorf(http.StatusForbidden, "Network not allowed in project"))
Expand Down
4 changes: 4 additions & 0 deletions doc/api-extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -2550,3 +2550,7 @@ This introduces the ability to access the sub-path of a file system custom volum
## `projects_limits_disk_pool`

This introduces per-pool project disk limits, introducing a `limits.disk.pool.NAME` configuration option to the project limits.

## `network_ovn_isolated`

This allows using `none` as the uplink network for an OVN network, making the network isolated.
2 changes: 1 addition & 1 deletion doc/reference/network_ovn.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ The following configuration options are available for the `ovn` network type:

Key | Type | Condition | Default | Description
:-- | :-- | :-- | :-- | :--
`network` | string | - | - | Uplink network to use for external network access
`network` | string | - | - | Uplink network to use for external network access or `none` to keep isolated
`bridge.hwaddr` | string | - | - | MAC address for the bridge
`bridge.mtu` | integer | - | `1442` | Bridge MTU (default allows host to host Geneve tunnels)
`dns.domain` | string | - | `incus` | Domain to advertise to DHCP clients and use for DNS resolution
Expand Down
48 changes: 28 additions & 20 deletions internal/server/device/nic_ovn.go
Original file line number Diff line number Diff line change
Expand Up @@ -412,16 +412,20 @@ func (d *nicOVN) Start() (*deviceConfig.RunConfig, error) {

// Load uplink network config.
uplinkNetworkName := d.network.Config()["network"]

var uplink *api.Network
var uplinkConfig map[string]string

err = d.state.DB.Cluster.Transaction(context.TODO(), func(ctx context.Context, tx *db.ClusterTx) error {
_, uplink, _, err = tx.GetNetworkInAnyState(ctx, api.ProjectDefaultName, uplinkNetworkName)
if uplinkNetworkName != "none" {
err = d.state.DB.Cluster.Transaction(context.TODO(), func(ctx context.Context, tx *db.ClusterTx) error {
_, uplink, _, err = tx.GetNetworkInAnyState(ctx, api.ProjectDefaultName, uplinkNetworkName)

return err
})
if err != nil {
return nil, fmt.Errorf("Failed to load uplink network %q: %w", uplinkNetworkName, err)
return err
})
if err != nil {
return nil, fmt.Errorf("Failed to load uplink network %q: %w", uplinkNetworkName, err)
}

uplinkConfig = uplink.Config
}

// Setup the host network interface (if not nested).
Expand Down Expand Up @@ -611,7 +615,7 @@ func (d *nicOVN) Start() (*deviceConfig.RunConfig, error) {
DNSName: d.inst.Name(),
DeviceName: d.name,
DeviceConfig: d.config,
UplinkConfig: uplink.Config,
UplinkConfig: uplinkConfig,
LastStateIPs: lastStateIPs, // Pass in volatile last state IPs for use with sticky DHCPv4 hint.
}, nil)
if err != nil {
Expand Down Expand Up @@ -642,7 +646,7 @@ func (d *nicOVN) Start() (*deviceConfig.RunConfig, error) {

// Associated host side interface to OVN logical switch port (if not nested).
if integrationBridgeNICName != "" {
cleanup, err := d.setupHostNIC(integrationBridgeNICName, logicalPortName, uplink)
cleanup, err := d.setupHostNIC(integrationBridgeNICName, logicalPortName)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -782,27 +786,31 @@ func (d *nicOVN) Update(oldDevices deviceConfig.Devices, isRunning bool) error {
if isRunning {
// Load uplink network config.
uplinkNetworkName := d.network.Config()["network"]

var uplink *api.Network
var uplinkConfig map[string]string

err := d.state.DB.Cluster.Transaction(context.TODO(), func(ctx context.Context, tx *db.ClusterTx) error {
var err error
if uplinkNetworkName != "none" {
err := d.state.DB.Cluster.Transaction(context.TODO(), func(ctx context.Context, tx *db.ClusterTx) error {
var err error

_, uplink, _, err = tx.GetNetworkInAnyState(ctx, api.ProjectDefaultName, uplinkNetworkName)
_, uplink, _, err = tx.GetNetworkInAnyState(ctx, api.ProjectDefaultName, uplinkNetworkName)

return err
})
if err != nil {
return fmt.Errorf("Failed to load uplink network %q: %w", uplinkNetworkName, err)
return err
})
if err != nil {
return fmt.Errorf("Failed to load uplink network %q: %w", uplinkNetworkName, err)
}

uplinkConfig = uplink.Config
}

// Update OVN logical switch port for instance.
_, _, err = d.network.InstanceDevicePortStart(&network.OVNInstanceNICSetupOpts{
_, _, err := d.network.InstanceDevicePortStart(&network.OVNInstanceNICSetupOpts{
InstanceUUID: d.inst.LocalConfig()["volatile.uuid"],
DNSName: d.inst.Name(),
DeviceName: d.name,
DeviceConfig: d.config,
UplinkConfig: uplink.Config,
UplinkConfig: uplinkConfig,
}, removedACLs)
if err != nil {
return fmt.Errorf("Failed updating OVN port: %w", err)
Expand Down Expand Up @@ -1153,7 +1161,7 @@ func (d *nicOVN) Register() error {
return nil
}

func (d *nicOVN) setupHostNIC(hostName string, ovnPortName ovn.OVNSwitchPort, uplink *api.Network) (revert.Hook, error) {
func (d *nicOVN) setupHostNIC(hostName string, ovnPortName ovn.OVNSwitchPort) (revert.Hook, error) {
revert := revert.New()
defer revert.Fail()

Expand Down
Loading

0 comments on commit 8be6b15

Please sign in to comment.