Advertise and update node names on cluster config exchange

Closes #244
This commit is contained in:
Audrius Butkevicius 2014-08-14 23:15:26 +01:00
parent bc885f1d08
commit e8a679c280
7 changed files with 98 additions and 13 deletions

File diff suppressed because one or more lines are too long

View File

@ -274,6 +274,8 @@ func main() {
cfgFile := filepath.Join(confDir, "config.xml") cfgFile := filepath.Join(confDir, "config.xml")
go saveConfigLoop(cfgFile) go saveConfigLoop(cfgFile)
var myName string
// Load the configuration file, if it exists. // Load the configuration file, if it exists.
// If it does not, create a template. // If it does not, create a template.
@ -285,9 +287,15 @@ func main() {
l.Fatalln(err) l.Fatalln(err)
} }
cf.Close() cf.Close()
myCfg := cfg.GetNodeConfiguration(myID)
if myCfg == nil || myCfg.Name == "" {
myName, _ = os.Hostname()
} else {
myName = myCfg.Name
}
} else { } else {
l.Infoln("No config file; starting with empty defaults") l.Infoln("No config file; starting with empty defaults")
name, _ := os.Hostname() myName, _ = os.Hostname()
defaultRepo := filepath.Join(getHomeDir(), "Sync") defaultRepo := filepath.Join(getHomeDir(), "Sync")
cfg, err = config.Load(nil, myID) cfg, err = config.Load(nil, myID)
@ -302,7 +310,7 @@ func main() {
{ {
NodeID: myID, NodeID: myID,
Addresses: []string{"dynamic"}, Addresses: []string{"dynamic"},
Name: name, Name: myName,
}, },
} }
@ -365,7 +373,7 @@ func main() {
if err != nil { if err != nil {
l.Fatalln("leveldb.OpenFile():", err) l.Fatalln("leveldb.OpenFile():", err)
} }
m := model.NewModel(confDir, &cfg, "syncthing", Version, db) m := model.NewModel(confDir, &cfg, myName, "syncthing", Version, db)
nextRepo: nextRepo:
for i, repo := range cfg.Repositories { for i, repo := range cfg.Repositories {

View File

@ -140,6 +140,15 @@ func (cfg *Configuration) NodeMap() map[protocol.NodeID]NodeConfiguration {
return m return m
} }
func (cfg *Configuration) GetNodeConfiguration(nodeid protocol.NodeID) *NodeConfiguration {
for i, node := range cfg.Nodes {
if node.NodeID == nodeid {
return &cfg.Nodes[i]
}
}
return nil
}
func (cfg *Configuration) RepoMap() map[string]RepositoryConfiguration { func (cfg *Configuration) RepoMap() map[string]RepositoryConfiguration {
m := make(map[string]RepositoryConfiguration, len(cfg.Repositories)) m := make(map[string]RepositoryConfiguration, len(cfg.Repositories))
for _, r := range cfg.Repositories { for _, r := range cfg.Repositories {

View File

@ -440,7 +440,8 @@
<div class="form-group"> <div class="form-group">
<label translate for="name">Node Name</label> <label translate for="name">Node Name</label>
<input placeholder="Home Server" id="name" class="form-control" type="text" ng-model="currentNode.Name"></input> <input placeholder="Home Server" id="name" class="form-control" type="text" ng-model="currentNode.Name"></input>
<p translate class="help-block">Shown instead of Node ID in the cluster status.</p> <p translate ng-if="currentNode.NodeID == myID" class="help-block">Shown instead of Node ID in the cluster status. Will advertised to other nodes as an optional default name.</p>
<p translate ng-if="currentNode.NodeID != myID" class="help-block">Shown instead of Node ID in the cluster status. Will be updated to the name the node advertises if left empty.</p>
</div> </div>
<div class="form-group"> <div class="form-group">
<label translate for="addresses">Addresses</label> <label translate for="addresses">Addresses</label>

View File

@ -68,6 +68,7 @@ type Model struct {
cfg *config.Configuration cfg *config.Configuration
db *leveldb.DB db *leveldb.DB
nodeName string
clientName string clientName string
clientVersion string clientVersion string
@ -101,11 +102,12 @@ var (
// NewModel creates and starts a new model. The model starts in read-only mode, // NewModel creates and starts a new model. The model starts in read-only mode,
// where it sends index information to connected peers and responds to requests // where it sends index information to connected peers and responds to requests
// for file data without altering the local repository in any way. // for file data without altering the local repository in any way.
func NewModel(indexDir string, cfg *config.Configuration, clientName, clientVersion string, db *leveldb.DB) *Model { func NewModel(indexDir string, cfg *config.Configuration, nodeName, clientName, clientVersion string, db *leveldb.DB) *Model {
m := &Model{ m := &Model{
indexDir: indexDir, indexDir: indexDir,
cfg: cfg, cfg: cfg,
db: db, db: db,
nodeName: nodeName,
clientName: clientName, clientName: clientName,
clientVersion: clientVersion, clientVersion: clientVersion,
repoCfgs: make(map[string]config.RepositoryConfiguration), repoCfgs: make(map[string]config.RepositoryConfiguration),
@ -406,6 +408,14 @@ func (m *Model) ClusterConfig(nodeID protocol.NodeID, config protocol.ClusterCon
} else { } else {
m.nodeVer[nodeID] = config.ClientName + " " + config.ClientVersion m.nodeVer[nodeID] = config.ClientName + " " + config.ClientVersion
} }
name := config.GetOption("name")
if name != "" {
node := m.cfg.GetNodeConfiguration(nodeID)
if node != nil && node.Name == "" {
l.Infof("Node %s is called %q", nodeID, name)
node.Name = name
}
}
m.pmut.Unlock() m.pmut.Unlock()
l.Infof(`Node %s client is "%s %s"`, nodeID, config.ClientName, config.ClientVersion) l.Infof(`Node %s client is "%s %s"`, nodeID, config.ClientName, config.ClientVersion)
@ -838,6 +848,12 @@ func (m *Model) clusterConfig(node protocol.NodeID) protocol.ClusterConfigMessag
cm := protocol.ClusterConfigMessage{ cm := protocol.ClusterConfigMessage{
ClientName: m.clientName, ClientName: m.clientName,
ClientVersion: m.clientVersion, ClientVersion: m.clientVersion,
Options: []protocol.Option{
{
Key: "name",
Value: m.nodeName,
},
},
} }
m.rmut.RLock() m.rmut.RLock()

View File

@ -57,7 +57,7 @@ func init() {
func TestRequest(t *testing.T) { func TestRequest(t *testing.T) {
db, _ := leveldb.Open(storage.NewMemStorage(), nil) db, _ := leveldb.Open(storage.NewMemStorage(), nil)
m := NewModel("/tmp", &config.Configuration{}, "syncthing", "dev", db) m := NewModel("/tmp", &config.Configuration{}, "node", "syncthing", "dev", db)
m.AddRepo(config.RepositoryConfiguration{ID: "default", Directory: "testdata"}) m.AddRepo(config.RepositoryConfiguration{ID: "default", Directory: "testdata"})
m.ScanRepo("default") m.ScanRepo("default")
@ -94,7 +94,7 @@ func genFiles(n int) []protocol.FileInfo {
func BenchmarkIndex10000(b *testing.B) { func BenchmarkIndex10000(b *testing.B) {
db, _ := leveldb.Open(storage.NewMemStorage(), nil) db, _ := leveldb.Open(storage.NewMemStorage(), nil)
m := NewModel("/tmp", nil, "syncthing", "dev", db) m := NewModel("/tmp", nil, "node", "syncthing", "dev", db)
m.AddRepo(config.RepositoryConfiguration{ID: "default", Directory: "testdata"}) m.AddRepo(config.RepositoryConfiguration{ID: "default", Directory: "testdata"})
m.ScanRepo("default") m.ScanRepo("default")
files := genFiles(10000) files := genFiles(10000)
@ -107,7 +107,7 @@ func BenchmarkIndex10000(b *testing.B) {
func BenchmarkIndex00100(b *testing.B) { func BenchmarkIndex00100(b *testing.B) {
db, _ := leveldb.Open(storage.NewMemStorage(), nil) db, _ := leveldb.Open(storage.NewMemStorage(), nil)
m := NewModel("/tmp", nil, "syncthing", "dev", db) m := NewModel("/tmp", nil, "node", "syncthing", "dev", db)
m.AddRepo(config.RepositoryConfiguration{ID: "default", Directory: "testdata"}) m.AddRepo(config.RepositoryConfiguration{ID: "default", Directory: "testdata"})
m.ScanRepo("default") m.ScanRepo("default")
files := genFiles(100) files := genFiles(100)
@ -120,7 +120,7 @@ func BenchmarkIndex00100(b *testing.B) {
func BenchmarkIndexUpdate10000f10000(b *testing.B) { func BenchmarkIndexUpdate10000f10000(b *testing.B) {
db, _ := leveldb.Open(storage.NewMemStorage(), nil) db, _ := leveldb.Open(storage.NewMemStorage(), nil)
m := NewModel("/tmp", nil, "syncthing", "dev", db) m := NewModel("/tmp", nil, "node", "syncthing", "dev", db)
m.AddRepo(config.RepositoryConfiguration{ID: "default", Directory: "testdata"}) m.AddRepo(config.RepositoryConfiguration{ID: "default", Directory: "testdata"})
m.ScanRepo("default") m.ScanRepo("default")
files := genFiles(10000) files := genFiles(10000)
@ -134,7 +134,7 @@ func BenchmarkIndexUpdate10000f10000(b *testing.B) {
func BenchmarkIndexUpdate10000f00100(b *testing.B) { func BenchmarkIndexUpdate10000f00100(b *testing.B) {
db, _ := leveldb.Open(storage.NewMemStorage(), nil) db, _ := leveldb.Open(storage.NewMemStorage(), nil)
m := NewModel("/tmp", nil, "syncthing", "dev", db) m := NewModel("/tmp", nil, "node", "syncthing", "dev", db)
m.AddRepo(config.RepositoryConfiguration{ID: "default", Directory: "testdata"}) m.AddRepo(config.RepositoryConfiguration{ID: "default", Directory: "testdata"})
m.ScanRepo("default") m.ScanRepo("default")
files := genFiles(10000) files := genFiles(10000)
@ -149,7 +149,7 @@ func BenchmarkIndexUpdate10000f00100(b *testing.B) {
func BenchmarkIndexUpdate10000f00001(b *testing.B) { func BenchmarkIndexUpdate10000f00001(b *testing.B) {
db, _ := leveldb.Open(storage.NewMemStorage(), nil) db, _ := leveldb.Open(storage.NewMemStorage(), nil)
m := NewModel("/tmp", nil, "syncthing", "dev", db) m := NewModel("/tmp", nil, "node", "syncthing", "dev", db)
m.AddRepo(config.RepositoryConfiguration{ID: "default", Directory: "testdata"}) m.AddRepo(config.RepositoryConfiguration{ID: "default", Directory: "testdata"})
m.ScanRepo("default") m.ScanRepo("default")
files := genFiles(10000) files := genFiles(10000)
@ -207,7 +207,7 @@ func (FakeConnection) Statistics() protocol.Statistics {
func BenchmarkRequest(b *testing.B) { func BenchmarkRequest(b *testing.B) {
db, _ := leveldb.Open(storage.NewMemStorage(), nil) db, _ := leveldb.Open(storage.NewMemStorage(), nil)
m := NewModel("/tmp", nil, "syncthing", "dev", db) m := NewModel("/tmp", nil, "node", "syncthing", "dev", db)
m.AddRepo(config.RepositoryConfiguration{ID: "default", Directory: "testdata"}) m.AddRepo(config.RepositoryConfiguration{ID: "default", Directory: "testdata"})
m.ScanRepo("default") m.ScanRepo("default")
@ -259,3 +259,45 @@ func TestActivityMap(t *testing.T) {
t.Errorf("Incorrect least busy node %q", node) t.Errorf("Incorrect least busy node %q", node)
} }
} }
func TestNodeRename(t *testing.T) {
ccm := protocol.ClusterConfigMessage{
ClientName: "syncthing",
ClientVersion: "v0.9.4",
}
cfg, _ := config.Load(nil, node1)
cfg.Nodes = []config.NodeConfiguration{
{
NodeID: node1,
},
}
db, _ := leveldb.Open(storage.NewMemStorage(), nil)
m := NewModel("/tmp", &cfg, "node", "syncthing", "dev", db)
if cfg.Nodes[0].Name != "" {
t.Errorf("Node already has a name")
}
m.ClusterConfig(node1, ccm)
if cfg.Nodes[0].Name != "" {
t.Errorf("Node already has a name")
}
ccm.Options = []protocol.Option{
{
Key: "name",
Value: "tester",
},
}
m.ClusterConfig(node1, ccm)
if cfg.Nodes[0].Name != "tester" {
t.Errorf("Node did not get a name")
}
ccm.Options[0].Value = "tester2"
m.ClusterConfig(node1, ccm)
if cfg.Nodes[0].Name != "tester" {
t.Errorf("Node name got overwritten")
}
}

View File

@ -98,6 +98,15 @@ type ClusterConfigMessage struct {
Options []Option // max:64 Options []Option // max:64
} }
func (o *ClusterConfigMessage) GetOption(key string) string {
for _, option := range o.Options {
if option.Key == key {
return option.Value
}
}
return ""
}
type Repository struct { type Repository struct {
ID string // max:64 ID string // max:64
Nodes []Node // max:64 Nodes []Node // max:64