blob: 597c95f5823185b6616e222b758d5c339490526d [file] [log] [blame]
David K. Bainbridge215e0242017-09-05 23:18:24 -07001// Copyright 2017 the original author or authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package main
16
17import (
18 "encoding/json"
19 "github.com/Sirupsen/logrus"
20)
21
22/*
23 * Structure used to capture the cluster configuraiton for ONOS and
24 * generate the appropriate JSON
25 */
26
27// ClusterNode ONOS node information
28type ClusterNode struct {
29 ID string `json:"id,omitempty"`
30 IP string `json:"ip,omitempty"`
31 Port int `json:"port,omitempty"`
32}
33
34// ClusterPartition ONOS partition record
35type ClusterPartition struct {
36 ID int `json:"id,omitempty"`
37 Members []string `json:"members,omitempty"`
38}
39
40// ClusterConfig ONOS cluster configuration
41type ClusterConfig struct {
42 Name string `json:"name,omitempty"`
43 Nodes []ClusterNode `json:"nodes,omitempty"`
44 Partitions []ClusterPartition `json:"partitions,omitempty"`
45}
46
47func minInt(a, b int) int {
48 if a < b {
49 return a
50 }
51 return b
52}
53
54//
55func GenerateConfig(info *ClusterInfo, update chan []byte) {
56 if info == nil || info.Expected < 1 {
57 log.Debugf("Expected instance count, %d, less than cluster minimum, generating empty config",
58 info.Expected)
59 update <- make([]byte, 0)
60 return
61 } else if info.Expected != uint64(len(info.Nodes)) {
62 // If the expected and actual node count differ then don't update
63 // config, a node might come back ater all
64 log.Debugf("Expected instances, %d, differs from actual, %d, dropping",
65 info.Expected, len(info.Nodes))
66 return
67 }
68
69 // Verify connectivity to nodes on port 9876
70 if err := VerifyNodes(info.Nodes, 9876); err != nil {
71 // Not able to verify connection to ONOS cluster instance
72 // so do not generate cluster meta data
73 log.Debugf("Unable to verify connection to all nodes : %s, configuration not generated",
74 err.Error())
75 return
76 }
77
78 next := ClusterConfig{
79 Name: "default",
80 }
81 next.Nodes = make([]ClusterNode, len(info.Nodes))
82 for idx, node := range info.Nodes {
83 next.Nodes[idx].ID = node
84 next.Nodes[idx].IP = node
85 next.Nodes[idx].Port = 9876
86 }
87
88 // Select a partition count that make "sense" depending on number
89 // of nodes
90 count := 1
91 if len(info.Nodes) >= 5 {
92 count = 5
93 } else if len(info.Nodes) >= 3 {
94 count = 3
95 }
96 next.Partitions = make([]ClusterPartition, count)
97
98 log.Debugf("Generating config for %d nodes, with %d partitions",
99 len(info.Nodes), count)
100 start := 0
101 perPart := minInt(len(info.Nodes), 3)
102 for idx := 0; idx < count; idx += 1 {
103 next.Partitions[idx].ID = idx + 1
104 next.Partitions[idx].Members = make([]string, perPart)
105 for midx := 0; midx < perPart; midx += 1 {
106 key := (start + midx) % len(info.Nodes)
107 next.Partitions[idx].Members[midx] = info.Nodes[key]
108 }
109 start += 1
110 }
111
112 data, err := json.Marshal(&next)
113 if err != nil {
114 log.Errorf("Unable to marshal cluster configuration : %s", err.Error())
115 } else {
116 if log.Level == logrus.DebugLevel {
117 ppData, err := json.MarshalIndent(&next, "CONFIG: ", " ")
118 if err != nil {
119 log.Warnf("Unable to marshal cluster configuration, for debug : %s", err.Error())
120 } else {
121 log.Debug(string(ppData))
122 }
123 }
124 update <- data
125 }
126}