Skip to content

Commit

Permalink
NET-1440: scale test changes (#3014)
Browse files Browse the repository at this point in the history
* NET-1440 scale test changes

* fix UT error and add error info

* load metric data into cacha in startup

* remove debug info for metric

* add server telemetry and hasSuperAdmin to cache

* fix user UT case

* update sqlite connection string for performance

* update check-in TS in cache only if cache enabled

* update metric data in cache only if cache enabled and write to DB once in stop

* update server status in mq topic

* add failover existed to server status update

* only send mq messsage when there is server status change

* batch peerUpdate

* code changes for scale for review

* update UT case

* update mq client check

* mq connection code change

* revert server status update changes

* revert batch peerUpdate

* remove server status update info

* code changes based on review and setupmqtt in keepalive

* set the mq message order to false for PIN

* remove setupmqtt in keepalive

* recycle ip in node deletion

* update ip allocation logic

* remove ip addr cap

* remove ippool file

* update get extClient func

* remove ip from cache map when extClient is removed
  • Loading branch information
yabinma authored Aug 15, 2024
1 parent c551c48 commit 46b8fd2
Show file tree
Hide file tree
Showing 23 changed files with 388 additions and 53 deletions.
4 changes: 2 additions & 2 deletions controllers/enrollmentkeys.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,12 @@ func getEnrollmentKeys(w http.ResponseWriter, r *http.Request) {
ret := []*models.EnrollmentKey{}
for _, key := range keys {
key := key
if err = logic.Tokenize(key, servercfg.GetAPIHost()); err != nil {
if err = logic.Tokenize(&key, servercfg.GetAPIHost()); err != nil {
logger.Log(0, r.Header.Get("user"), "failed to get token values for keys:", err.Error())
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
return
}
ret = append(ret, key)
ret = append(ret, &key)
}
// return JSON/API formatted keys
logger.Log(2, r.Header.Get("user"), "fetched enrollment keys")
Expand Down
2 changes: 1 addition & 1 deletion controllers/hosts.go
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,7 @@ func authenticateHost(response http.ResponseWriter, request *http.Request) {
errorResponse.Code = http.StatusBadRequest
errorResponse.Message = err.Error()
logger.Log(0, request.Header.Get("user"),
"error retrieving host: ", err.Error())
"error retrieving host: ", authRequest.ID, err.Error())
logic.ReturnErrorResponse(response, request, errorResponse)
return
}
Expand Down
6 changes: 6 additions & 0 deletions controllers/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,8 @@ func deleteNetwork(w http.ResponseWriter, r *http.Request) {
logic.ReturnErrorResponse(w, r, logic.FormatError(err, errtype))
return
}
//delete network from allocated ip map
go logic.RemoveNetworkFromAllocatedIpMap(network)

logger.Log(1, r.Header.Get("user"), "deleted network", network)
w.WriteHeader(http.StatusOK)
Expand Down Expand Up @@ -480,6 +482,10 @@ func createNetwork(w http.ResponseWriter, r *http.Request) {
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
return
}

//add new network to allocated ip map
go logic.AddNetworkToAllocatedIpMap(network.NetID)

go func() {
defaultHosts := logic.GetDefaultHosts()
for i := range defaultHosts {
Expand Down
4 changes: 2 additions & 2 deletions controllers/network_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ func TestCreateNetwork(t *testing.T) {
deleteAllNetworks()

var network models.Network
network.NetID = "skynet"
network.AddressRange = "10.0.0.1/24"
network.NetID = "skynet1"
network.AddressRange = "10.10.0.1/24"
// if tests break - check here (removed displayname)
//network.DisplayName = "mynetwork"

Expand Down
2 changes: 1 addition & 1 deletion controllers/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ func authenticate(response http.ResponseWriter, request *http.Request) {
errorResponse.Code = http.StatusBadRequest
errorResponse.Message = err.Error()
logger.Log(0, request.Header.Get("user"),
"error retrieving host: ", err.Error())
"error retrieving host: ", result.HostID.String(), err.Error())
logic.ReturnErrorResponse(response, request, errorResponse)
return
}
Expand Down
1 change: 1 addition & 0 deletions controllers/user_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ func TestCreateUser(t *testing.T) {

func TestCreateSuperAdmin(t *testing.T) {
deleteAllUsers(t)
logic.ClearSuperUserCache()
var user models.User
t.Run("NoSuperAdmin", func(t *testing.T) {
user.UserName = "admin"
Expand Down
18 changes: 17 additions & 1 deletion logic/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,21 @@ const (
auth_key = "netmaker_auth"
)

var (
superUser = models.User{}
)

func ClearSuperUserCache() {
superUser = models.User{}
}

// HasSuperAdmin - checks if server has an superadmin/owner
func HasSuperAdmin() (bool, error) {

if superUser.IsSuperAdmin {
return true, nil
}

collection, err := database.FetchRecords(database.USERS_TABLE_NAME)
if err != nil {
if database.IsEmptyRecord(err) {
Expand All @@ -38,6 +50,7 @@ func HasSuperAdmin() (bool, error) {
continue
}
if user.IsSuperAdmin {
superUser = user
return true, nil
}
}
Expand Down Expand Up @@ -116,7 +129,7 @@ func CreateUser(user *models.User) error {

tokenString, _ := CreateUserJWT(user.UserName, user.IsSuperAdmin, user.IsAdmin)
if tokenString == "" {
logger.Log(0, "failed to generate token", err.Error())
logger.Log(0, "failed to generate token")
return err
}

Expand Down Expand Up @@ -204,6 +217,9 @@ func UpsertUser(user models.User) error {
slog.Error("error inserting user", "user", user.UserName, "error", err.Error())
return err
}
if user.IsSuperAdmin {
superUser = user
}
return nil
}

Expand Down
73 changes: 58 additions & 15 deletions logic/enrollmentkey.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ import (
"encoding/json"
"errors"
"fmt"
"sync"
"time"

"github.com/google/uuid"
"github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/servercfg"
"golang.org/x/exp/slices"
)

Expand All @@ -29,6 +31,10 @@ var EnrollmentErrors = struct {
FailedToTokenize: fmt.Errorf("failed to tokenize"),
FailedToDeTokenize: fmt.Errorf("failed to detokenize"),
}
var (
enrollmentkeyCacheMutex = &sync.RWMutex{}
enrollmentkeyCacheMap = make(map[string]models.EnrollmentKey)
)

// CreateEnrollmentKey - creates a new enrollment key in db
func CreateEnrollmentKey(uses int, expiration time.Time, networks, tags []string, unlimited bool, relay uuid.UUID) (*models.EnrollmentKey, error) {
Expand Down Expand Up @@ -104,21 +110,21 @@ func UpdateEnrollmentKey(keyId string, relayId uuid.UUID) (*models.EnrollmentKey

key.Relay = relayId

if err = upsertEnrollmentKey(key); err != nil {
if err = upsertEnrollmentKey(&key); err != nil {
return nil, err
}

return key, nil
return &key, nil
}

// GetAllEnrollmentKeys - fetches all enrollment keys from DB
// TODO drop double pointer
func GetAllEnrollmentKeys() ([]*models.EnrollmentKey, error) {
func GetAllEnrollmentKeys() ([]models.EnrollmentKey, error) {
currentKeys, err := getEnrollmentKeysMap()
if err != nil {
return nil, err
}
var currentKeysList = []*models.EnrollmentKey{}
var currentKeysList = []models.EnrollmentKey{}
for k := range currentKeys {
currentKeysList = append(currentKeysList, currentKeys[k])
}
Expand All @@ -127,15 +133,21 @@ func GetAllEnrollmentKeys() ([]*models.EnrollmentKey, error) {

// GetEnrollmentKey - fetches a single enrollment key
// returns nil and error if not found
func GetEnrollmentKey(value string) (*models.EnrollmentKey, error) {
func GetEnrollmentKey(value string) (key models.EnrollmentKey, err error) {
currentKeys, err := getEnrollmentKeysMap()
if err != nil {
return nil, err
return key, err
}
if key, ok := currentKeys[value]; ok {
return key, nil
}
return nil, EnrollmentErrors.NoKeyFound
return key, EnrollmentErrors.NoKeyFound
}

func deleteEnrollmentkeyFromCache(key string) {
enrollmentkeyCacheMutex.Lock()
delete(enrollmentkeyCacheMap, key)
enrollmentkeyCacheMutex.Unlock()
}

// DeleteEnrollmentKey - delete's a given enrollment key by value
Expand All @@ -144,7 +156,13 @@ func DeleteEnrollmentKey(value string) error {
if err != nil {
return err
}
return database.DeleteRecord(database.ENROLLMENT_KEYS_TABLE_NAME, value)
err = database.DeleteRecord(database.ENROLLMENT_KEYS_TABLE_NAME, value)
if err == nil {
if servercfg.CacheEnabled() {
deleteEnrollmentkeyFromCache(value)
}
}
return err
}

// TryToUseEnrollmentKey - checks first if key can be decremented
Expand Down Expand Up @@ -200,7 +218,7 @@ func DeTokenize(b64Token string) (*models.EnrollmentKey, error) {
if err != nil {
return nil, err
}
return k, nil
return &k, nil
}

// == private ==
Expand All @@ -215,11 +233,11 @@ func decrementEnrollmentKey(value string) (*models.EnrollmentKey, error) {
return nil, EnrollmentErrors.NoUsesRemaining
}
k.UsesRemaining = k.UsesRemaining - 1
if err = upsertEnrollmentKey(k); err != nil {
if err = upsertEnrollmentKey(&k); err != nil {
return nil, err
}

return k, nil
return &k, nil
}

func upsertEnrollmentKey(k *models.EnrollmentKey) error {
Expand All @@ -230,7 +248,13 @@ func upsertEnrollmentKey(k *models.EnrollmentKey) error {
if err != nil {
return err
}
return database.Insert(k.Value, string(data), database.ENROLLMENT_KEYS_TABLE_NAME)
err = database.Insert(k.Value, string(data), database.ENROLLMENT_KEYS_TABLE_NAME)
if err == nil {
if servercfg.CacheEnabled() {
storeEnrollmentkeyInCache(k.Value, *k)
}
}
return nil
}

func getUniqueEnrollmentID() (string, error) {
Expand All @@ -245,7 +269,23 @@ func getUniqueEnrollmentID() (string, error) {
return newID, nil
}

func getEnrollmentKeysMap() (map[string]*models.EnrollmentKey, error) {
func getEnrollmentkeysFromCache() map[string]models.EnrollmentKey {
return enrollmentkeyCacheMap
}

func storeEnrollmentkeyInCache(key string, enrollmentkey models.EnrollmentKey) {
enrollmentkeyCacheMutex.Lock()
enrollmentkeyCacheMap[key] = enrollmentkey
enrollmentkeyCacheMutex.Unlock()
}

func getEnrollmentKeysMap() (map[string]models.EnrollmentKey, error) {
if servercfg.CacheEnabled() {
keys := getEnrollmentkeysFromCache()
if len(keys) != 0 {
return keys, nil
}
}
records, err := database.FetchRecords(database.ENROLLMENT_KEYS_TABLE_NAME)
if err != nil {
if !database.IsEmptyRecord(err) {
Expand All @@ -255,14 +295,17 @@ func getEnrollmentKeysMap() (map[string]*models.EnrollmentKey, error) {
if records == nil {
records = make(map[string]string)
}
currentKeys := make(map[string]*models.EnrollmentKey, 0)
currentKeys := make(map[string]models.EnrollmentKey, 0)
if len(records) > 0 {
for k := range records {
var currentKey models.EnrollmentKey
if err = json.Unmarshal([]byte(records[k]), &currentKey); err != nil {
continue
}
currentKeys[k] = &currentKey
currentKeys[k] = currentKey
if servercfg.CacheEnabled() {
storeEnrollmentkeyInCache(currentKey.Value, currentKey)
}
}
}
return currentKeys, nil
Expand Down
2 changes: 1 addition & 1 deletion logic/enrollmentkey_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ func TestDelete_EnrollmentKey(t *testing.T) {
err := DeleteEnrollmentKey(newKey.Value)
assert.Nil(t, err)
oldKey, err := GetEnrollmentKey(newKey.Value)
assert.Nil(t, oldKey)
assert.Equal(t, oldKey, models.EnrollmentKey{})
assert.NotNil(t, err)
assert.Equal(t, err, EnrollmentErrors.NoKeyFound)
})
Expand Down
19 changes: 19 additions & 0 deletions logic/extpeers.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,21 @@ func DeleteExtClient(network string, clientid string) error {
if err != nil {
return err
}
extClient, err := GetExtClient(clientid, network)
if err != nil {
return err
}
err = database.DeleteRecord(database.EXT_CLIENT_TABLE_NAME, key)
if err != nil {
return err
}
//recycle ip address
if extClient.Address != "" {
RemoveIpFromAllocatedIpMap(network, extClient.Address)
}
if extClient.Address6 != "" {
RemoveIpFromAllocatedIpMap(network, extClient.Address6)
}
if servercfg.CacheEnabled() {
deleteExtClientFromCache(key)
}
Expand Down Expand Up @@ -287,6 +298,14 @@ func SaveExtClient(extclient *models.ExtClient) error {
if servercfg.CacheEnabled() {
storeExtClientInCache(key, *extclient)
}
if _, ok := allocatedIpMap[extclient.Network]; ok {
if extclient.Address != "" {
AddIpToAllocatedIpMap(extclient.Network, net.ParseIP(extclient.Address))
}
if extclient.Address6 != "" {
AddIpToAllocatedIpMap(extclient.Network, net.ParseIP(extclient.Address6))
}
}
return SetNetworkNodesLastModified(extclient.Network)
}

Expand Down
2 changes: 1 addition & 1 deletion logic/jwts.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func SetJWTSecret() {

// CreateJWT func will used to create the JWT while signing in and signing out
func CreateJWT(uuid string, macAddress string, network string) (response string, err error) {
expirationTime := time.Now().Add(5 * time.Minute)
expirationTime := time.Now().Add(15 * time.Minute)
claims := &models.Claims{
ID: uuid,
Network: network,
Expand Down
Loading

0 comments on commit 46b8fd2

Please sign in to comment.