Newer
Older
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
package main
import (
"context"
"encoding/json"
"fmt"
"time"
"code.fbi.h-da.de/danet/gosdn/api/go/gosdn/device"
"code.fbi.h-da.de/danet/gosdn/application-framework/models"
"code.fbi.h-da.de/danet/gosdn/models/generated/arista"
"github.com/google/uuid"
"github.com/openconfig/ygot/ygot"
"github.com/openconfig/ygot/ytypes"
)
var statusMap map[string]map[string]*InterfaceStatus
// NetworkElement is a NetworkElement.
type NetworkElement struct {
// UUID represents the Devices UUID
UUID uuid.UUID
// Name is the device's human readable Name
Name string
// Device embeds a ygot.GoStruct containing the device details
Model arista.Device
}
// NewNetworkElement creates a new NetworkElement.
func NewNetworkElement(id uuid.UUID, name string, deviceModel string) *NetworkElement {
d := &NetworkElement{
UUID: id,
Model: arista.Device{},
Name: name,
}
// Create 'root' path to be able to load the whole model from the store.
path, err := ygot.StringToPath("/", ygot.StructuredPath)
if err != nil {
panic(err)
}
opts := []ytypes.UnmarshalOpt{
&ytypes.IgnoreExtraFields{},
}
// Use unmarshall from the devices SBI to unmarshall ygot json in go struct.
err = models.Unmarshal([]byte(deviceModel), path, &d.Model, opts...)
if err != nil {
panic(err)
}
return d
}
type InterfaceStatus struct {
NetworkElementName string
Name string
Status string
}
func checkIfOperationStateHasChanged(deviceServer device.DeviceServiceClient, networkElementID uuid.UUID) ([]InterfaceStatus, error) {
ctx := context.Background()
request := &device.GetDeviceRequest{
Timestamp: time.Now().UnixNano(),
DeviceID: networkElementID.String(),
}
resp, err := deviceServer.Get(ctx, request)
if err != nil {
return nil, err
}
networkElement := NewNetworkElement(uuid.MustParse(resp.Device.Id), resp.Device.Name, resp.Device.Model)
storedInterfaces, ok := statusMap[networkElement.Name]
if !ok {
addDeviceToStatusMap(networkElement.Name, *&networkElement.Model.Interfaces.Interface)
return nil, nil
}
return walkThroughInterfaces(*&networkElement.Model.Interfaces.Interface, storedInterfaces)
}
func addDeviceToStatusMap(networkElementName string, interfaces map[string]*arista.OpenconfigInterfaces_Interfaces_Interface) {
statusList := make(map[string]*InterfaceStatus)
for _, receivedInterface := range interfaces {
statusList[*receivedInterface.Name] = &InterfaceStatus{
NetworkElementName: networkElementName,
Name: *receivedInterface.Name,
Status: receivedInterface.State.OperStatus.String(),
}
}
statusMap[networkElementName] = statusList
}
func walkThroughInterfaces(interfaces map[string]*arista.OpenconfigInterfaces_Interfaces_Interface, storedInterfaces map[string]*InterfaceStatus) ([]InterfaceStatus, error) {
statusList := make([]InterfaceStatus, 0)
for _, receivedInterface := range interfaces {
storedInterface, ok := storedInterfaces[*receivedInterface.Name]
if !ok {
return statusList, fmt.Errorf("could not find %s in stored interfaces", *receivedInterface.Name)
}
if storedInterface.Status != receivedInterface.State.OperStatus.String() {
statusList = append(statusList, InterfaceStatus{
NetworkElementName: storedInterface.NetworkElementName,
Name: *receivedInterface.Name,
Status: receivedInterface.State.OperStatus.String(),
})
storedInterface.Status = receivedInterface.State.OperStatus.String()
statusMapCopy := statusMap
go func() {
b, err := json.Marshal(statusMapCopy)
if err != nil {
return
}
for clientChannel := range clientChannels {
clientChannel <- []byte(b)
}
}()
}
}