mirror of https://github.com/jetkvm/kvm.git
186 lines
5.2 KiB
Go
186 lines
5.2 KiB
Go
package kvm
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
|
|
"github.com/jetkvm/kvm/internal/network"
|
|
"github.com/jetkvm/kvm/internal/ota"
|
|
"github.com/jetkvm/kvm/internal/udhcpc"
|
|
)
|
|
|
|
const (
|
|
NetIfName = "eth0"
|
|
)
|
|
|
|
var (
|
|
networkState *network.NetworkInterfaceState
|
|
)
|
|
|
|
func networkStateChanged(isOnline bool) {
|
|
// do not block the main thread
|
|
go waitCtrlAndRequestDisplayUpdate(true, "network_state_changed")
|
|
|
|
if timeSync != nil {
|
|
if networkState != nil {
|
|
timeSync.SetDhcpNtpAddresses(networkState.NtpAddressesString())
|
|
}
|
|
|
|
if err := timeSync.Sync(); err != nil {
|
|
networkLogger.Error().Err(err).Msg("failed to sync time after network state change")
|
|
}
|
|
}
|
|
|
|
// always restart mDNS when the network state changes
|
|
if mDNS != nil {
|
|
_ = mDNS.SetListenOptions(config.NetworkConfig.GetMDNSMode())
|
|
_ = mDNS.SetLocalNames([]string{
|
|
networkState.GetHostname(),
|
|
networkState.GetFQDN(),
|
|
}, true)
|
|
}
|
|
|
|
// if the network is now online, trigger an NTP sync if still needed
|
|
if isOnline && timeSync != nil && (isTimeSyncNeeded() || !timeSync.IsSyncSuccess()) {
|
|
if err := timeSync.Sync(); err != nil {
|
|
logger.Warn().Str("error", err.Error()).Msg("unable to sync time on network state change")
|
|
}
|
|
}
|
|
}
|
|
|
|
func initNetwork() error {
|
|
ensureConfigLoaded()
|
|
|
|
state, err := network.NewNetworkInterfaceState(&network.NetworkInterfaceOptions{
|
|
DefaultHostname: GetDefaultHostname(),
|
|
InterfaceName: NetIfName,
|
|
NetworkConfig: config.NetworkConfig,
|
|
Logger: networkLogger,
|
|
OnStateChange: func(state *network.NetworkInterfaceState) {
|
|
networkStateChanged(state.IsOnline())
|
|
},
|
|
OnInitialCheck: func(state *network.NetworkInterfaceState) {
|
|
networkStateChanged(state.IsOnline())
|
|
},
|
|
OnDhcpLeaseChange: func(lease *udhcpc.Lease, state *network.NetworkInterfaceState) {
|
|
networkStateChanged(state.IsOnline())
|
|
|
|
if currentSession == nil {
|
|
return
|
|
}
|
|
|
|
writeJSONRPCEvent("networkState", networkState.RpcGetNetworkState(), currentSession)
|
|
},
|
|
OnConfigChange: func(networkConfig *network.NetworkConfig) {
|
|
config.NetworkConfig = networkConfig
|
|
networkStateChanged(false)
|
|
|
|
if mDNS != nil {
|
|
_ = mDNS.SetListenOptions(networkConfig.GetMDNSMode())
|
|
_ = mDNS.SetLocalNames([]string{
|
|
networkState.GetHostname(),
|
|
networkState.GetFQDN(),
|
|
}, true)
|
|
}
|
|
},
|
|
})
|
|
}
|
|
|
|
func setHostname(nm *nmlite.NetworkManager, hostname, domain string) error {
|
|
if nm == nil {
|
|
return nil
|
|
}
|
|
|
|
if hostname == "" {
|
|
hostname = GetDefaultHostname()
|
|
}
|
|
|
|
return nm.SetHostname(hostname, domain)
|
|
}
|
|
|
|
func shouldRebootForNetworkChange(oldConfig, newConfig *types.NetworkConfig) (rebootRequired bool, postRebootAction *ota.PostRebootAction) {
|
|
oldDhcpClient := oldConfig.DHCPClient.String
|
|
|
|
l := networkLogger.With().
|
|
Interface("old", oldConfig).
|
|
Interface("new", newConfig).
|
|
Logger()
|
|
|
|
// DHCP client change always requires reboot
|
|
if newConfig.DHCPClient.String != oldDhcpClient {
|
|
rebootRequired = true
|
|
l.Info().Msg("DHCP client changed, reboot required")
|
|
return rebootRequired, postRebootAction
|
|
}
|
|
|
|
oldIPv4Mode := oldConfig.IPv4Mode.String
|
|
newIPv4Mode := newConfig.IPv4Mode.String
|
|
|
|
// IPv4 mode change requires reboot
|
|
if newIPv4Mode != oldIPv4Mode {
|
|
rebootRequired = true
|
|
l.Info().Msg("IPv4 mode changed with udhcpc, reboot required")
|
|
|
|
if newIPv4Mode == "static" && oldIPv4Mode != "static" {
|
|
postRebootAction = &ota.PostRebootAction{
|
|
HealthCheck: fmt.Sprintf("//%s/device/status", newConfig.IPv4Static.Address.String),
|
|
RedirectTo: fmt.Sprintf("//%s", newConfig.IPv4Static.Address.String),
|
|
}
|
|
l.Info().Interface("postRebootAction", postRebootAction).Msg("IPv4 mode changed to static, reboot required")
|
|
}
|
|
|
|
return rebootRequired, postRebootAction
|
|
}
|
|
|
|
// IPv4 static config changes require reboot
|
|
if !reflect.DeepEqual(oldConfig.IPv4Static, newConfig.IPv4Static) {
|
|
rebootRequired = true
|
|
|
|
// Handle IP change for redirect (only if both are not nil and IP changed)
|
|
if newConfig.IPv4Static != nil && oldConfig.IPv4Static != nil &&
|
|
newConfig.IPv4Static.Address.String != oldConfig.IPv4Static.Address.String {
|
|
postRebootAction = &ota.PostRebootAction{
|
|
HealthCheck: fmt.Sprintf("//%s/device/status", newConfig.IPv4Static.Address.String),
|
|
RedirectTo: fmt.Sprintf("//%s", newConfig.IPv4Static.Address.String),
|
|
}
|
|
|
|
l.Info().Interface("postRebootAction", postRebootAction).Msg("IPv4 static config changed, reboot required")
|
|
}
|
|
|
|
return rebootRequired, postRebootAction
|
|
}
|
|
|
|
// IPv6 mode change requires reboot when using udhcpc
|
|
if newConfig.IPv6Mode.String != oldConfig.IPv6Mode.String && oldDhcpClient == "udhcpc" {
|
|
rebootRequired = true
|
|
l.Info().Msg("IPv6 mode changed with udhcpc, reboot required")
|
|
}
|
|
|
|
return rebootRequired, postRebootAction
|
|
}
|
|
|
|
func rpcGetNetworkState() network.RpcNetworkState {
|
|
return networkState.RpcGetNetworkState()
|
|
}
|
|
|
|
func rpcGetNetworkSettings() network.RpcNetworkSettings {
|
|
return networkState.RpcGetNetworkSettings()
|
|
}
|
|
|
|
func rpcSetNetworkSettings(settings network.RpcNetworkSettings) (*network.RpcNetworkSettings, error) {
|
|
s := networkState.RpcSetNetworkSettings(settings)
|
|
if s != nil {
|
|
return nil, s
|
|
}
|
|
|
|
if err := SaveConfig(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &network.RpcNetworkSettings{NetworkConfig: *config.NetworkConfig}, nil
|
|
}
|
|
|
|
func rpcRenewDHCPLease() error {
|
|
return networkState.RpcRenewDHCPLease()
|
|
}
|