Skip to content
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

v0.20.6 #544

Merged
merged 16 commits into from
Aug 17, 2023
Merged
Show file tree
Hide file tree
Changes from 15 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
2 changes: 1 addition & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func Execute() {
}

func init() {
cobra.OnInitialize(initConfig, functions.Migrate)
cobra.OnInitialize(functions.Migrate, initConfig)
// Here you will define your flags and configuration settings.
// Cobra supports persistent flags, which, if defined here,
// will be global for your application.
Expand Down
7 changes: 1 addition & 6 deletions config/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,6 @@ func ConvertNode(nodeGet *models.NodeGet) *Node {
//node.Password = netmakerNode.Password
node.NetworkRange = nodeGet.Node.NetworkRange
node.NetworkRange6 = nodeGet.Node.NetworkRange6
node.InternetGateway = nodeGet.Node.InternetGateway
//n.Interface = s.Interface
node.Server = netmakerNode.Server
node.Connected = nodeGet.Node.Connected
Expand All @@ -160,17 +159,13 @@ func ConvertToNetmakerNode(node *Node, server *Server, host *Config) *models.Leg
var netmakerNode models.LegacyNode
netmakerNode.ID = node.ID.String()
netmakerNode.OS = host.OS
netmakerNode.HostID = server.MQID.String()
//netmakerNode.HostID = server.MQID.String()
netmakerNode.Name = host.Name
netmakerNode.Network = node.Network
netmakerNode.Password = host.HostPass
netmakerNode.AccessKey = server.AccessKey
netmakerNode.NetworkSettings.AddressRange = node.NetworkRange.String()
netmakerNode.NetworkSettings.AddressRange6 = node.NetworkRange6.String()
netmakerNode.InternetGateway = ""
if node.InternetGateway != nil {
netmakerNode.InternetGateway = node.InternetGateway.IP.String()
}
netmakerNode.Interface = ncutils.GetInterfaceName()
netmakerNode.Interfaces = host.Interfaces
netmakerNode.Server = node.Server
Expand Down
2 changes: 0 additions & 2 deletions config/oldconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,6 @@ func ConvertOldNode(netmakerNode *models.LegacyNode) (*Node, *Config) {
node.Network = netmakerNode.Network
node.NetworkRange = ToIPNet(netmakerNode.NetworkSettings.AddressRange)
node.NetworkRange6 = ToIPNet(netmakerNode.NetworkSettings.AddressRange6)
node.InternetGateway = ToUDPAddr(netmakerNode.InternetGateway)
host.Interfaces = netmakerNode.Interfaces
host.EndpointIP = net.ParseIP(netmakerNode.Endpoint)
node.Connected = ParseBool(netmakerNode.Connected)
Expand All @@ -142,7 +141,6 @@ func ConvertOldNode(netmakerNode *models.LegacyNode) (*Node, *Config) {
node.Network = netmakerNode.Network
node.NetworkRange = ToIPNet(netmakerNode.NetworkSettings.AddressRange)
node.NetworkRange6 = ToIPNet(netmakerNode.NetworkSettings.AddressRange6)
node.InternetGateway = ToUDPAddr(netmakerNode.InternetGateway)
host.Interfaces = netmakerNode.Interfaces
host.EndpointIP = net.ParseIP(netmakerNode.Endpoint)
node.Connected = ParseBool(netmakerNode.Connected)
Expand Down
6 changes: 3 additions & 3 deletions daemon/common_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func install() error {
func start() error {
host := config.Netclient()
if !host.DaemonInstalled {
return errors.New("netclient daemon not installed")
slog.Warn("netclient daemon not installed")
}
switch host.InitType {
case config.Systemd:
Expand All @@ -73,7 +73,7 @@ func start() error {
func stop() error {
host := config.Netclient()
if !host.DaemonInstalled {
return errors.New("netclient daemon not installed")
slog.Warn("netclient daemon not installed")
}
switch host.InitType {
case config.Systemd:
Expand All @@ -95,7 +95,7 @@ func stop() error {
func hardRestart() error {
host := config.Netclient()
if !host.DaemonInstalled {
return errors.New("systemd not installed .. daemon not started")
slog.Warn("netclient daemon not installed")
}
switch host.InitType {
case config.Systemd:
Expand Down
4 changes: 3 additions & 1 deletion functions/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ func Install() error {
fmt.Println(" eg ./netclient install")
return errors.New("path error")
}
_ = daemon.Stop()
if err := daemon.Stop(); err != nil {
slog.Warn("stopping netclient daemon", "error", err)
}
time.Sleep(time.Second << 1)
if err := daemon.Install(); err != nil {
slog.Error("daemon install error", "error", err)
Expand Down
194 changes: 108 additions & 86 deletions functions/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,29 @@ package functions

import (
"errors"
"fmt"
"net/http"
"os"
"strconv"
"strings"

"github.com/devilcove/httpclient"
"github.com/gravitl/netclient/config"
"github.com/gravitl/netclient/daemon"
"github.com/gravitl/netclient/ncutils"
"github.com/gravitl/netclient/wireguard"
"github.com/gravitl/netmaker/logger"
"github.com/gravitl/netmaker/models"
"golang.org/x/exp/slog"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
)

// Migrate update data from older versions of netclient to new format
// TODO fix it
func Migrate() {
servers := make(map[string][]models.LegacyNode)
slog.Info("migration func")
delete := true
hostname, err := os.Hostname()
if err != nil {
slog.Warn("set hostname", "error", err)
}
config_dir := config.GetNetclientPath()
if !ncutils.IsWindows() {
config_dir += "config"
Expand All @@ -29,80 +33,60 @@ func Migrate() {
//nothing to migrate ... exiting"
return
}
logger.Log(0, "migration to v0.18 started")
networks, err := config.GetSystemNetworks()
if err != nil {
fmt.Println("error reading network data ", err.Error())
slog.Error("reading network data", "error", err)
return
}
if len(networks) == 0 { // nothing to migrate
slog.Warn("no networks, nothing to migrate")
return
}
logger.Log(0, "stopping daemon")
slog.Info("stopping daemon")
if err := daemon.Stop(); err != nil {
logger.Log(0, "failed to stop daemon", err.Error())
slog.Warn("stopping daemon failed", "error", err)
}

logger.Log(0, "networks to be migrated", strings.Join(networks, " "))
var legacyNodes = []models.LegacyNode{}
var servers = map[string]struct{}{}
var newHost models.Host
if config.Netclient().ListenPort == 0 {
config.Netclient().ListenPort = 51821
}
slog.Info("networks to be migrated " + strings.Join(networks, " "))

for _, network := range networks {
logger.Log(0, "migrating", network)
slog.Info("migrating " + network)
if err := removeHostDNS(network); err != nil {
slog.Error("remove host DNS", "error", err)
}
cfg, err := config.ReadConfig(network)
if err != nil {
logger.Log(0, "failed to read config for network", network, "skipping ...")
slog.Error("skipping network, could not read config", "network", network, "error", err)
continue
}
serverName := strings.Replace(cfg.Server.Server, "broker.", "", 1)
oldIface := cfg.Node.Interface
secretPath := config.GetNetclientPath() + "config/secret-" + network
if ncutils.IsWindows() {
secretPath = config.GetNetclientPath() + "secret-" + network
}
pass, err := os.ReadFile(secretPath)
if err != nil {
logger.Log(0, "could not read secrets file", err.Error())
slog.Error("read secrets file", "error", err)
continue
}
cfg.Node.Password = string(pass)
legacyNodes = append(legacyNodes, cfg.Node)
node, netclient := config.ConvertOldNode(&cfg.Node)
node.Server = strings.Replace(cfg.Server.Server, "broker.", "", 1)
servers[cfg.Server.API] = struct{}{}
newHost, _ = config.Convert(netclient, node)
newHost.PublicKey = netclient.PrivateKey.PublicKey()
ip, err := getInterfaces()
if err != nil {
logger.Log(0, "failed to retrieve local interfaces", err.Error())
} else {
if ip != nil {
newHost.Interfaces = *ip
}
}
defaultInterface, err := getDefaultInterface()
if err != nil {
logger.Log(0, "default gateway not found", err.Error())
} else if defaultInterface != ncutils.GetInterfaceName() {
newHost.DefaultInterface = defaultInterface
}
cfg.Node.Server = serverName
wireguard.DeleteOldInterface(oldIface)
nodes := servers[serverName]
servers[serverName] = append(nodes, cfg.Node)
}
if newHost.ListenPort == 0 {
newHost.ListenPort = config.Netclient().ListenPort
}
var serversToWrite = []models.ServerConfig{}
for k := range servers {
server := k
logger.Log(0, "migrating for server", server)
hostSet := false
for k, v := range servers {
//server := k
slog.Info("server migration", "server", k)
migrationData := models.MigrationData{
LegacyNodes: legacyNodes,
NewHost: newHost,
HostName: hostname,
Password: v[0].Password,
LegacyNodes: v,
}
api := httpclient.JSONEndpoint[models.RegisterResponse, models.ErrorResponse]{
URL: "https://" + server,
api := httpclient.JSONEndpoint[models.HostPull, models.ErrorResponse]{
URL: "https://api." + k,
Route: "/api/v1/nodes/migrate",
Method: http.MethodPost,
Headers: []httpclient.Header{
Expand All @@ -112,62 +96,100 @@ func Migrate() {
},
},
Data: migrationData,
Response: models.RegisterResponse{},
Response: models.HostPull{},
ErrorResponse: models.ErrorResponse{},
}
migrateResponse, errData, err := api.GetJSON(models.RegisterResponse{}, models.ErrorResponse{})
migrateResponse, errData, err := api.GetJSON(models.HostPull{}, models.ErrorResponse{})
if err != nil {
logger.Log(0, "err migrating data", err.Error())
slog.Error("migration response", "error", err)
if errors.Is(err, httpclient.ErrStatus) {
logger.Log(0, "error migrating server", server, strconv.Itoa(errData.Code), errData.Message)
delete = false
continue
slog.Error("status error", "code", errData.Code, "message", errData.Message)
}
delete = false
continue
}
if !IsVersionComptatible(migrateResponse.ServerConf.Version) {
logger.Log(0, "incompatible server version", migrateResponse.ServerConf.Version)
if !IsVersionComptatible(migrateResponse.ServerConfig.Version) {
slog.Error("incompatible server version", "server", migrateResponse.ServerConfig.Version, "client", config.Netclient().Version)
delete = false
continue
}
serversToWrite = append(serversToWrite, migrateResponse.ServerConf)
newHost.ListenPort = migrateResponse.RequestedHost.ListenPort

}
if len(migrateResponse.Nodes) == 0 {
slog.Error("no nodes returned")
delete = false
continue
}
if !hostSet {
slog.Info("setting host")
netclient := config.Netclient()
netclient.Host = migrateResponse.Host
netclient.PrivateKey = getWGPrivateKey(migrateResponse.Nodes[0].Network)
netclient.TrafficKeyPrivate = getOldTrafficKey(migrateResponse.Nodes[0].Network)
netclient.HostPass = getOldPassword(migrateResponse.Nodes[0].Network)

for i := range legacyNodes {
network := legacyNodes[i].Network
_ = removeHostDNS(network) // remove old DNS
if err := config.WriteNetclientConfig(); err != nil {
slog.Error("write config", "error", err)
}
hostSet = true
}
slog.Info("updating server config")
config.SaveServer(k, config.Server{
ServerConfig: migrateResponse.ServerConfig,
Name: k,
MQID: migrateResponse.Host.ID,
})
slog.Info("updating node")
config.SetNodes(migrateResponse.Nodes)
if err := config.WriteNodeConfig(); err != nil {
slog.Error("save node config", "error", err)
}
slog.Info("publish host update", "server", k, "update", models.UpdateHost)
server := config.GetServer(k)
if err := setupMQTTSingleton(server, true); err != nil {
slog.Error("mqtt setup", "error", err)
continue
}
if err := PublishHostUpdate(k, models.UpdateHost); err != nil {
slog.Error("pub host update", "server", k, "error", err)
}
}

if delete {
logger.Log(3, "removing old config files")
if err := os.RemoveAll(config.GetNetclientPath()); err != nil {
logger.Log(0, "failed to delete old configuration files ", err.Error())
slog.Info("removing old config files")
if err := os.Rename(config.GetNetclientPath()+"/config", config.GetNetclientPath()+"/config.old"); err != nil {
//if err := os.RemoveAll(config.GetNetclientPath()); err != nil {
slog.Error("deleting config files", "error", err)
}
}

for i := range serversToWrite {
serverValue := serversToWrite[i]
config.UpdateServerConfig(&serverValue)
newServerConfig := config.GetServer(serverValue.Server)
if newServerConfig == nil {
continue
}
config.UpdateServer(serverValue.Server, *newServerConfig)
if err := config.SaveServer(serverValue.Server, *newServerConfig); err != nil {
logger.Log(0, "failed to save server", err.Error())
} else {
logger.Log(0, "saved server", serverValue.Server)
}
}
_ = daemon.Restart()
}

if config.Netclient().ListenPort == 0 {
config.Netclient().ListenPort = 51821
func getWGPrivateKey(network string) wgtypes.Key {
data, err := os.ReadFile(config.GetNetclientPath() + "config/wgkey-" + network)
if err != nil {
slog.Error("read wireguard key", "error", err)
return wgtypes.Key{}
}
key, err := wgtypes.ParseKey(string(data))
if err != nil {
slog.Error("parse key", "error", err)
return wgtypes.Key{}
}
return key
}

if err := config.WriteNetclientConfig(); err != nil {
logger.Log(0, "error saving netclient config during migrate", err.Error())
func getOldTrafficKey(network string) []byte {
data, err := os.ReadFile(config.GetNetclientPath() + "/config/traffic-" + network)
if err != nil {
slog.Error("read old traffic key", "error", err)
}
return data
}

_ = daemon.Restart()
func getOldPassword(network string) string {
data, err := os.ReadFile(config.GetNetclientPath() + "/config/secret-" + network)
if err != nil {
slog.Error("read password", "error", err)
}
return string(data)
}
2 changes: 2 additions & 0 deletions functions/mqhandlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,8 @@ func HostUpdate(client mqtt.Client, msg mqtt.Message) {
case models.UpdateKeys:
clearRetainedMsg(client, msg.Topic()) // clear message
UpdateKeys()
case models.RequestPull:
Pull(true)
default:
slog.Error("unknown host action", "action", hostUpdate.Action)
return
Expand Down
Loading