Skip to content
Snippets Groups Projects
network-element.go 3.7 KiB
Newer Older
  • Learn to ignore specific revisions
  • 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
    	}
    
    
    Malte Bauch's avatar
    Malte Bauch committed
    	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
    }
    
    
    Malte Bauch's avatar
    Malte Bauch committed
    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 {
    
    Malte Bauch's avatar
    Malte Bauch committed
    			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 {
    
    Malte Bauch's avatar
    Malte Bauch committed
    					fmt.Println("error: ", err)
    
    					return
    				}
    				for clientChannel := range clientChannels {
    					clientChannel <- []byte(b)
    				}
    			}()
    		}
    	}
    
    
    Malte Bauch's avatar
    Malte Bauch committed
    	return statusList, nil