Skip to content
Merged
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
2 changes: 2 additions & 0 deletions platform/os_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ const (
CNMRuntimePath = "/var/lib/azure-network/"
// CNIRuntimePath is the path where CNI state files are stored.
CNIRuntimePath = "/var/run/"
// CNILockPath is the path where CNI lock files are stored.
CNILockPath = "/var/lock/azure-vnet/"
// CNSRuntimePath is the path where CNS state files are stored.
CNSRuntimePath = "/var/run/"
// CNI runtime path on a Kubernetes cluster
Expand Down
3 changes: 3 additions & 0 deletions platform/os_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ const (
// CNIRuntimePath is the path where CNI state files are stored.
CNIRuntimePath = ""

// CNILockPath is the path where CNI lock files are stored.
CNILockPath = ""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we make this also in separate dir?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is windows and can update this when required. i leave it to current behaviour


// CNI runtime path on a Kubernetes cluster
K8SCNIRuntimePath = "C:\\k\\azurecni\\bin"

Expand Down
26 changes: 16 additions & 10 deletions store/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const (
// jsonFileStore is an implementation of KeyValueStore using a local JSON file.
type jsonFileStore struct {
fileName string
lockFileName string
data map[string]*json.RawMessage
inSync bool
locked bool
Expand All @@ -46,8 +47,16 @@ func NewJsonFileStore(fileName string) (KeyValueStore, error) {
fileName = defaultFileName
}

if platform.CNILockPath != "" {
err := os.MkdirAll(platform.CNILockPath, os.FileMode(0664))
if err != nil {
return nil, err
}
}

kvs := &jsonFileStore{
fileName: fileName,
lockFileName: platform.CNILockPath + filepath.Base(fileName) + lockExtension,
data: make(map[string]*json.RawMessage),
}

Expand Down Expand Up @@ -166,15 +175,14 @@ func (kvs *jsonFileStore) Lock(block bool) error {

var lockFile *os.File
var err error
lockName := kvs.fileName + lockExtension
lockPerm := os.FileMode(0664) + os.FileMode(os.ModeExclusive)

// Try to acquire the lock file.
var lockRetryCount uint
var modTimeCur time.Time
var modTimePrev time.Time
for lockRetryCount < lockMaxRetries {
lockFile, err = os.OpenFile(lockName, os.O_CREATE|os.O_EXCL|os.O_RDWR, lockPerm)
lockFile, err = os.OpenFile(kvs.lockFileName, os.O_CREATE|os.O_EXCL|os.O_RDWR, lockPerm)
if err == nil {
break
}
Expand All @@ -184,7 +192,7 @@ func (kvs *jsonFileStore) Lock(block bool) error {
}

// Reset the lock retry count if the timestamp for the lock file changes.
if fileInfo, err := os.Stat(lockName); err == nil {
if fileInfo, err := os.Stat(kvs.lockFileName); err == nil {
modTimeCur = fileInfo.ModTime()
if !modTimeCur.Equal(modTimePrev) {
lockRetryCount = 0
Expand Down Expand Up @@ -222,7 +230,7 @@ func (kvs *jsonFileStore) Unlock(forceUnlock bool) error {
return ErrStoreNotLocked
}

err := os.Remove(kvs.fileName + lockExtension)
err := os.Remove(kvs.lockFileName)
if err != nil {
return err
}
Expand Down Expand Up @@ -252,27 +260,25 @@ func (kvs *jsonFileStore) GetLockFileModificationTime() (time.Time, error) {
kvs.Mutex.Lock()
defer kvs.Mutex.Unlock()

lockFileName := kvs.fileName + lockExtension

// Check if the file exists.
file, err := os.Open(lockFileName)
file, err := os.Open(kvs.lockFileName)
if err != nil {
return time.Time{}.UTC(), err
}

defer file.Close()

info, err := os.Stat(lockFileName)
info, err := os.Stat(kvs.lockFileName)
if err != nil {
log.Printf("os.stat() for file %v failed: %v", lockFileName, err)
log.Printf("os.stat() for file %v failed: %v", kvs.lockFileName, err)
return time.Time{}.UTC(), err
}

return info.ModTime().UTC(), nil
}

func (kvs *jsonFileStore) GetLockFileName() string {
return kvs.fileName + lockExtension
return kvs.lockFileName
}

func (kvs *jsonFileStore) Remove() {
Expand Down
36 changes: 35 additions & 1 deletion store/json_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ package store

import (
"os"
"runtime"
"strings"
"testing"
)

const (
// File name used for test store.
testFileName = "test.json"

testLockFileName = "locktest.json"
// Keys used during tests.
testKey1 = "key1"
testKey2 = "key2"
Expand Down Expand Up @@ -206,3 +207,36 @@ func TestLockingStoreGivesExclusiveAccess(t *testing.T) {
// Cleanup.
os.Remove(testFileName)
}

// test case for testing newjsonfilestore idempotent
func TestNewJsonFileStoreIdempotent(t *testing.T) {
_, err := NewJsonFileStore(testLockFileName)
if err != nil {
t.Errorf("Failed to initialize store: %v", err)
}

_, err = NewJsonFileStore(testLockFileName)
if err != nil {
t.Errorf("Failed to initialize same store second time: %v", err)
}
}

// test case for checking if lockfilepath is expected
func TestLockFilePath(t *testing.T) {
store, err := NewJsonFileStore(testLockFileName)
if err != nil {
t.Errorf("Failed to initialize store: %v", err)
}

lockFileName := store.GetLockFileName()

if runtime.GOOS == "linux" {
if lockFileName != "/var/lock/azure-vnet/" + testLockFileName + ".lock" {
t.Errorf("Not expected file lock name: %v", lockFileName)
}
} else {
if lockFileName != testLockFileName + ".lock" {
t.Errorf("Not expected lockfilename: %v", lockFileName)
}
}
}