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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package nucleus
import (
"fmt"
spb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/southbound"
"code.fbi.h-da.de/danet/gosdn/controller/event"
eventInterfaces "code.fbi.h-da.de/danet/gosdn/controller/interfaces/event"
"code.fbi.h-da.de/danet/gosdn/controller/interfaces/networkelement"
"code.fbi.h-da.de/danet/gosdn/controller/interfaces/southbound"
"code.fbi.h-da.de/danet/gosdn/controller/store"
"github.com/google/uuid"
"github.com/openconfig/ygot/ygot"
tpb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/transport"
log "github.com/sirupsen/logrus"
)
const (
// NetworkElementEventTopic is the used topic for network element related entity changes.
NetworkElementEventTopic = "managedNetworkElement"
)
// NetworkElementService provides a network element service implementation.
// This services provides abstraction between the user (e.g a PND) and the matching store (e.g. networkElementStore).
type NetworkElementService struct {
networkElementStore networkelement.Store
sbiService southbound.Service
eventService eventInterfaces.Service
}
// NewNetworkElementService creates a network element service.
func NewNetworkElementService(
networkElementStore networkelement.Store,
sbiService southbound.Service,
eventService eventInterfaces.Service,
) networkelement.Service {
return &NetworkElementService{
networkElementStore: networkElementStore,
sbiService: sbiService,
eventService: eventService,
}
}
// Get takes a network element's UUID or name and returns the network element.
func (s *NetworkElementService) Get(query store.Query) (networkelement.NetworkElement, error) {
loadedNetworkElement, err := s.networkElementStore.Get(query)
if err != nil {
return nil, err
}
mne, err := s.createNetworkElementFromStore(loadedNetworkElement)
if err != nil {
return nil, err
}
return mne, nil
}
// GetAll returns all stored network elements.
func (s *NetworkElementService) GetAll() ([]networkelement.NetworkElement, error) {
var mnes []networkelement.NetworkElement
loadedNetworkElements, err := s.networkElementStore.GetAll()
if err != nil {
return nil, err
}
for _, loadedNetworkElement := range loadedNetworkElements {
mne, err := s.createNetworkElementFromStore(loadedNetworkElement)
if err != nil {
return nil, err
}
mnes = append(mnes, mne)
}
return mnes, nil
}
// GetAllAsLoaded returns all stored network elements as LoadedNetworkElement.
// This method should be used if there is no need for a networkelement.NetworkElement, since
// requesting network element information through this method is a lot faster than the
// usual `GetAll` method.
func (s *NetworkElementService) GetAllAsLoaded() ([]networkelement.LoadedNetworkElement, error) {
loadedNetworkElements, err := s.networkElementStore.GetAll()
if err != nil {
return nil, err
}
return loadedNetworkElements, nil
}
// Add adds a network element to the network element store.
func (s *NetworkElementService) Add(networkElementToAdd networkelement.NetworkElement) error {
err := s.networkElementStore.Add(networkElementToAdd)
if err != nil {
return err
}
Fabian Seidl
committed
pubEvent := event.NewAddEvent(networkElementToAdd.ID())
if err := s.eventService.PublishEvent(NetworkElementEventTopic, pubEvent); err != nil {
go func() {
s.eventService.Reconnect()
retryErr := s.eventService.RetryPublish(NetworkElementEventTopic, pubEvent)
if retryErr != nil {
log.Error(retryErr)
}
}()
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
}
return nil
}
// UpdateModel updates a existing network element with a new model provided as string.
func (s *NetworkElementService) UpdateModel(networkElementToUpdate networkelement.NetworkElement, modelAsString string) error {
exisitingNetworkElement, err := s.Get(store.Query{ID: networkElementToUpdate.ID()})
if err != nil {
return err
}
// Create 'root' path to be able to load the whole model from the store.
path, err := ygot.StringToPath("/", ygot.StructuredPath)
if err != nil {
return err
}
// Use unmarshall from the network elements SBI to unmarshall ygot json in go struct.
err = exisitingNetworkElement.SBI().Unmarshal([]byte(modelAsString), path, exisitingNetworkElement.GetModel())
if err != nil {
return err
}
err = s.networkElementStore.Update(exisitingNetworkElement)
if err != nil {
return err
}
Fabian Seidl
committed
pubEvent := event.NewUpdateEvent(networkElementToUpdate.ID())
if err := s.eventService.PublishEvent(NetworkElementEventTopic, pubEvent); err != nil {
go func() {
s.eventService.Reconnect()
retryErr := s.eventService.RetryPublish(NetworkElementEventTopic, pubEvent)
if retryErr != nil {
log.Error(retryErr)
}
}()
}
return nil
}
// Update updates a existing network element.
func (s *NetworkElementService) Update(networkElementToUpdate networkelement.NetworkElement) error {
err := s.networkElementStore.Update(networkElementToUpdate)
if err != nil {
return err
}
Fabian Seidl
committed
pubEvent := event.NewUpdateEvent(networkElementToUpdate.ID())
if err := s.eventService.PublishEvent(NetworkElementEventTopic, pubEvent); err != nil {
go func() {
s.eventService.Reconnect()
retryErr := s.eventService.RetryPublish(NetworkElementEventTopic, pubEvent)
if retryErr != nil {
log.Error(retryErr)
}
}()
}
return nil
}
// Delete deletes a network element from the network element store.
func (s *NetworkElementService) Delete(networkElementToDelete networkelement.NetworkElement) error {
err := s.networkElementStore.Delete(networkElementToDelete)
if err != nil {
return err
}
if networkElementToDelete.SBI().Type() == spb.Type_TYPE_PLUGIN {
err = s.sbiService.Delete(networkElementToDelete.SBI())
if err != nil {
return err
}
}
Fabian Seidl
committed
pubEvent := event.NewDeleteEvent(networkElementToDelete.ID())
if err := s.eventService.PublishEvent(NetworkElementEventTopic, pubEvent); err != nil {
go func() {
s.eventService.Reconnect()
retryErr := s.eventService.RetryPublish(NetworkElementEventTopic, pubEvent)
if retryErr != nil {
log.Error(retryErr)
}
}()
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
}
return nil
}
func (s *NetworkElementService) createNetworkElementFromStore(loadedNetworkElement networkelement.LoadedNetworkElement) (networkelement.NetworkElement, error) {
if loadedNetworkElement.SBI == "" {
return nil, fmt.Errorf("no sbi found for network element")
}
sbiForNetworkElement, err := s.sbiService.Get(store.Query{ID: uuid.MustParse(loadedNetworkElement.SBI)})
if err != nil {
return nil, err
}
mne, err := NewNetworkElement(
loadedNetworkElement.Name,
uuid.MustParse(loadedNetworkElement.ID),
&tpb.TransportOption{
Address: loadedNetworkElement.TransportAddress,
Username: loadedNetworkElement.TransportUsername,
Password: loadedNetworkElement.TransportPassword,
TransportOption: &tpb.TransportOption_GnmiTransportOption{
GnmiTransportOption: &tpb.GnmiTransportOption{},
},
Type: spb.Type_TYPE_OPENCONFIG,
}, sbiForNetworkElement)
if err != nil {
return nil, err
}
// Create 'root' path to be able to load the whole model from the store.
path, err := ygot.StringToPath("/", ygot.StructuredPath)
if err != nil {
return nil, err
}
// Use unmarshall from the network elements SBI to unmarshall ygot json in go struct.
err = mne.SBI().Unmarshal([]byte(loadedNetworkElement.Model), path, mne.GetModel())
if err != nil {
return nil, err
}
return mne, nil
}