-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
175 lines (142 loc) · 5.83 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
package main
import (
"fmt"
ygotsrl "steiler/yangtest/generated/srl"
"steiler/yangtest/generated/sros"
"github.com/openconfig/ygot/ygot"
)
func main() {
srosDevice := &ygotsros.Device{}
}
func old_main() {
// First lets prepare some stuff.
// retieve a simple very small config, which we consider the actual config
// this would be cached in the controller and probably come from an array, in which all the configs are stored / cached.
actualConfig := &ygotsrl.Device{}
//actualConfig := loadConfigFromFile("/home/steiler/projects/yangtest/configwim2 init.json")
// // Uncomment to add ethernet-1-50 description and stuff to the actual config, this is to check for the MergeOverwrite functionality
// appendE150(actualConfig)
// retrieve a config snippet defining a subinterface as well as the network-instance as default for the /system/ssh-server
// this would be the spec with which the controller would be triggered
//specConfig := loadConfigFromFile("/home/steiler/projects/yangtest/configwim2 copy.json")
specConfig := loadConfigFromFile("/home/steiler/projects/yangtest/configwim3.json")
// lets start our "fake" reconsiliation
DoComparisonAndPathEvaluation(actualConfig, specConfig)
}
// this is where we drive the whole stuff,
// basically parts of the reconsiliation
func DoComparisonAndPathEvaluation(actualConfig *ygotsrl.Device, specConfig *ygotsrl.Device) {
// validate the actual config
err := actualConfig.Validate()
if err != nil {
panic(err)
}
// skipping specValidation, this will probably result in missing leaf leafrefs
newConfigTmp, err := ygot.DeepCopy(actualConfig)
if err != nil {
panic(err)
}
newConfig := newConfigTmp.(*ygotsrl.Device) // Typecast
// Merge spec into newconfig, which is right now jsut the actual config
err = ygot.MergeStructInto(newConfig, specConfig)
if err != nil {
panic(err)
}
// validate the new config
err = newConfig.Validate()
if err != nil {
panic(err)
}
// create a diff of the actual compared to the to-become-new config
actualVsSpecDiff, err := ygot.Diff(actualConfig, newConfig)
if err != nil {
panic(err)
}
fmt.Println("GNMI Notification Content:")
printGnmiNotification(actualVsSpecDiff)
fmt.Println("")
// calculate the relevant paths (As wim calls them, Root Paths)
//_ = CarveOutRelevantSubPaths(actualVsSpecDiff)
fmt.Println("Relevant Hier-Paths:")
// get Root Schema
// schema, err := ygotsrl.Schema()
// if err != nil {
// panic(err)
// }
// deviceSchema := schema.RootSchema()
// Feed schema and diff *gnmi.Update into rootpath library
//rootConfigElement := rootpaths.ConfigElementHierarchyFromGnmiUpdate(deviceSchema, actualVsSpecDiff)
// // get and print Rootpaths
// printGnmiPaths(rootConfigElement.GetRootPaths())
// fmt.Println(rootConfigElement.GetHierarchicalOutput(" "))
fmt.Println("All good, made it to the end!")
}
/* // Carve out the sub-paths that have a specific relevance from a gnmi.Notification.
//
// We go down the tree to find the paths where values are actually changed or deleted
// and returns a list of these gnmi.Path's in an aggregated way.
// Or put it, returns the absolute path to the root of the elements which will be touched in the gnmi.Notification.
func CarveOutRelevantSubPaths(gn *gnmi.Notification) []*gnmi.Path {
//retrieve the root schema which is required in the following
rootSchema := getRootSchema()
// initialize storage for all the relevant paths
allPathSchemas := []*PathAndSchema{}
for _, elem := range gn.GetUpdate() {
// for each update check that it is no default value, we want to skip those.
pathAndSchemaElem := getPathAndSchemaEntry(rootSchema, elem.Path)
allPathSchemas = append(allPathSchemas, pathAndSchemaElem)
runhierarchical(pathAndSchemaElem)
}
fmt.Println(rootCE.getHierarchicalOutput(0, " "))
// aggregate the deduced paths to find the common relevant base paths
AggregateSpecSignificantPaths := aggregateCommonPaths(allPathSchemas, rootSchema)
for _, ps := range AggregateSpecSignificantPaths {
fmt.Println(ps.String())
}
return append(gn.GetDelete())
}
*/
/* // checks if the provided gnmi.Update just sets the key for the corresponding entry or any other related data.
func isKeyValue(schemaEntry *yang.Entry, u *gnmi.Update) bool {
return schemaEntry.Parent.Key == u.Path.Elem[len(u.Path.Elem)-1].Name
}
// checks if the provided gnmi.Update just sets a value to the default value of a leaf
func isDefaultValue(schemaEntry *yang.Entry, u *gnmi.Update) bool {
if defval, singleDefVal := schemaEntry.SingleDefaultValue(); singleDefVal {
return u.Val.GetStringVal() == defval
}
return false
} */
/*
// aggregates the proivided paths by extratcting relevant paths
func aggregateCommonPaths(p []*PathAndSchema, rootSchema *yang.Entry) []*PathAndSchemaCount {
// we add the first path straight away to the list, therrefore make sure we have at least 1 entry in the list
result := []*PathAndSchemaCount{}
if len(p) == 0 {
return result
}
// append the first struct to the result slice
result = append(result, &PathAndSchemaCount{p[0], 1})
var found bool
// iterate over all paths
for _, elem := range p[1 : len(p)-1] {
found = false
// compare to existing paths in result
for resultIndex, resultElem := range result {
// extract the common path of the actual elem and the path from the actual result paths entry
cp := ygotutils.FindPathElemPrefix([]*gnmi.Path{elem.path, resultElem.path})
if cp != nil && len(cp.Elem) > 0 {
newPath := &gnmi.Path{Elem: cp.Elem}
// create a new PathAndSchema struct taking the previouse count incremented by 1
result[resultIndex] = &PathAndSchemaCount{getPathAndSchemaEntry(rootSchema, newPath), resultElem.count + 1}
found = true
break
}
}
if !found {
// there was no match for such path so we add it to the result with a count of 1
result = append(result, &PathAndSchemaCount{elem, 1})
}
}
return result
} */