Skip to content
Snippets Groups Projects
networkElement.go 11 KiB
Newer Older
  • Learn to ignore specific revisions
  • Manuel Kieweg's avatar
    Manuel Kieweg committed
    package nucleus
    
    import (
    
    	spb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/southbound"
    	tpb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/transport"
    
    	"code.fbi.h-da.de/danet/gosdn/controller/conflict"
    
    	"code.fbi.h-da.de/danet/gosdn/controller/interfaces/networkelement"
    
    	"code.fbi.h-da.de/danet/gosdn/controller/interfaces/plugin"
    
    	"code.fbi.h-da.de/danet/gosdn/controller/interfaces/transport"
    
    	"github.com/docker/docker/pkg/namesgenerator"
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	"github.com/google/uuid"
    	"github.com/openconfig/ygot/ygot"
    
    	"go.mongodb.org/mongo-driver/bson"
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	"google.golang.org/protobuf/proto"
    
    // NewNetworkElement creates a network element.
    
    func NewNetworkElement(
    	name string,
    	uuidInput uuid.UUID,
    	opt *tpb.TransportOption,
    
    	metadata conflict.Metadata,
    ) (networkelement.NetworkElement, error) {
    
    	t, err := NewTransport(opt, plugin)
    
    	if err != nil {
    		return nil, err
    	}
    
    	// TODO: this needs to check the case that the uuidInput is set, as the
    	// same uuid may be already stored.
    
    	if uuidInput == uuid.Nil {
    		uuidInput = uuid.New()
    
    	}
    
    	if name == "" {
    		name = namesgenerator.GetRandomName(0)
    	}
    
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    	if opt.Type == spb.Type_TYPE_CONTAINERISED {
    
    		return &CsbiNetworkElement{
    			CommonNetworkElement: CommonNetworkElement{
    
    				transport:        t,
    				name:             name,
    				transportOptions: opt,
    
    	return &CommonNetworkElement{
    
    		transport:        t,
    		name:             name,
    		transportOptions: opt,
    
    // CommonNetworkElement represents an MNE.
    type CommonNetworkElement struct {
    	// UUID represents the Network Elements UUID
    
    	UUID uuid.UUID
    
    	// Plugin embeds a gosdn ygot plugin. Allows to work on a devices config
    	// based its supported YANG models. The code for this is generated through
    	// ygot.
    	Plugin plugin.Plugin
    
    	// Transport is the network element's Transport implementation
    
    	transport transport.Transport
    
    	// Name is the network element's human readable name
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	name string
    
    
    	transportOptions *tpb.TransportOption
    
    
    	Metadata conflict.Metadata
    
    // ID returns the UUID of the Network Element.
    func (n *CommonNetworkElement) ID() uuid.UUID {
    	return n.UUID
    
    // GetModel returns the ygot representation of the Network Element.
    
    func (d *CommonNetworkElement) GetModel() ([]byte, error) {
    
    	return d.Plugin.Model()
    
    // GetModelAsFilteredCopy returns the ygot representation of the Network
    // Element, but as copy with read-only fields removed.
    
    Malte Bauch's avatar
    Malte Bauch committed
    // TODO: extend plugin to provide a filtered copy of the model.
    
    func (n *CommonNetworkElement) GetModelAsFilteredCopy() (ygot.GoStruct, error) {
    
    	//filteredModelCopy, err := createFilteredCopy(n)
    	//if err != nil {
    	//	return nil, err
    	//}
    	//return filteredModelCopy, nil
    	return nil, fmt.Errorf("not implemented yet")
    
    }
    
    // SetModel sets the ygot representation of the Network Element.
    
    Malte Bauch's avatar
    Malte Bauch committed
    // TODO: check if needed; if this is the case, then extend plugin to provide this functionality.
    
    func (n *CommonNetworkElement) SetModel(model ygot.GoStruct) {
    
    }
    
    // Transport returns the Transport of the network element.
    func (n *CommonNetworkElement) Transport() transport.Transport {
    	return n.transport
    
    // Transport returns the Transport of the network element.
    func (d *CommonNetworkElement) GetPlugin() plugin.Plugin {
    
    // TransportAddress returns the TransportAddress of the network element.
    func (n *CommonNetworkElement) TransportAddress() string {
    	return n.transportOptions.Address
    
    // Name returns the name of the network element.
    func (n *CommonNetworkElement) Name() string {
    	return n.name
    
    // SetTransport sets the Network Element's Transport.
    func (n *CommonNetworkElement) SetTransport(t transport.Transport) {
    	n.transport = t
    
    // SetName sets the Network Element's name.
    func (n *CommonNetworkElement) SetName(name string) {
    	n.name = name
    
    // ProcessResponse processes a response for the Network Element.
    
    func (d *CommonNetworkElement) ProcessResponse(resp proto.Message) error {
    
    	return d.transport.ProcessResponse(resp)
    
    // IsTransportValid returns a boolean if the transport of a network element is valid.
    func (n *CommonNetworkElement) IsTransportValid() bool {
    	if n.transportOptions != nil && n.transportOptions.Address != "" {
    
    // GetMetadata returns the metadate of a network element.
    func (n *CommonNetworkElement) GetMetadata() conflict.Metadata {
    	return n.Metadata
    }
    
    
    // CsbiNetworkElement is used for the cSBI functionality.
    type CsbiNetworkElement struct {
    	CommonNetworkElement
    
    // ID returns the UUID of the Network Element.
    func (n *CsbiNetworkElement) ID() uuid.UUID {
    	return n.UUID
    
    // GetModel returns the ygot representation of the Network Element.
    
    func (d *CsbiNetworkElement) GetModel() ([]byte, error) {
    
    	return d.Plugin.Model()
    
    // GetModelAsFilteredCopy returns the ygot representation of the Network
    // Element, but as copy with read-only fields removed.
    
    Malte Bauch's avatar
    Malte Bauch committed
    // TODO: extend plugin to provide a filtered copy of the model.
    
    func (n *CsbiNetworkElement) GetModelAsFilteredCopy() (ygot.GoStruct, error) {
    
    	//filteredModelCopy, err := createFilteredCopy(n)
    	//if err != nil {
    	//	return nil, err
    	//}
    	//return filteredModelCopy, nil
    	return nil, fmt.Errorf("not implemented yet")
    
    }
    
    // SetModel returns the ygot representation of the Network Element.
    
    Malte Bauch's avatar
    Malte Bauch committed
    // TODO: check if needed; if this is the case, then extend plugin to provide this functionality.
    
    func (n *CsbiNetworkElement) SetModel(model ygot.GoStruct) {
    
    }
    
    // Transport returns the Transport of the network element.
    func (n *CsbiNetworkElement) Transport() transport.Transport {
    	return n.transport
    
    // Transport returns the Transport of the device.
    
    func (d *CsbiNetworkElement) GetPlugin() plugin.Plugin {
    
    // Name returns the name of the network element.
    func (n *CsbiNetworkElement) Name() string {
    	return n.name
    
    // GetMetadata returns the metadate of a network element.
    func (n *CsbiNetworkElement) GetMetadata() conflict.Metadata {
    	return n.Metadata
    }
    
    
    // ProcessResponse processes a response for the Network Element.
    
    func (d *CsbiNetworkElement) ProcessResponse(resp proto.Message) error {
    
    	// TODO: callback to send response to caller
    
    	return d.transport.ProcessResponse(resp)
    
    // IsTransportValid returns a boolean if the transport of a network element is valid.
    func (n *CsbiNetworkElement) IsTransportValid() bool {
    	if n.transportOptions != nil && n.transportOptions.Address != "" {
    
    // MarshalJSON implements the MarshalJSON interface to store a network element as JSON.
    func (n *CommonNetworkElement) MarshalJSON() ([]byte, error) {
    
    	var transportType string
    	var transportAddress string
    	var transportUsername string
    	var transportPassword string
    
    Malte Bauch's avatar
    Malte Bauch committed
    	var transportOptionType spb.Type
    
    	// Handling of these cases is necessary as we use partial network elements for testing.
    
    	// eg. in most tests no transport or sbi is defined.
    	// The marshaller will crash if we want to access a nil field.
    
    	if n.transport == nil || n.transportOptions == nil {
    
    		transportType = "testing"
    		transportAddress = "testing"
    		transportUsername = "testing"
    		transportPassword = "testing"
    
    Fabian Seidl's avatar
    Fabian Seidl committed
    		transportOptionType = spb.Type_TYPE_OPENCONFIG
    
    		transportType = n.transport.Type()
    		transportAddress = n.transportOptions.Address
    		transportUsername = n.transportOptions.Username
    		transportPassword = n.transportOptions.Password
    		transportOptionType = n.transportOptions.Type
    
    	pluginUUID := n.Plugin.ID()
    
    Andre Sterba's avatar
    Andre Sterba committed
    	if err != nil {
    		return []byte{}, err
    	}
    
    
    	return json.Marshal(&struct {
    
    		ID                  uuid.UUID `json:"id,omitempty"`
    
    		Name                string    `json:"name,omitempty"`
    		TransportType       string    `json:"transport_type,omitempty"`
    		TransportAddress    string    `json:"transport_address,omitempty"`
    		TransportUsername   string    `json:"transport_username,omitempty"`
    		TransportPassword   string    `json:"transport_password,omitempty"`
    
    Malte Bauch's avatar
    Malte Bauch committed
    		TransportOptionType spb.Type  `json:"transport_option"`
    
    		Plugin              uuid.UUID `json:"plugin,omitempty"`
    
    Andre Sterba's avatar
    Andre Sterba committed
    		Model               string    `bson:"model,omitempty"`
    
    		TransportType:       transportType,
    		TransportAddress:    transportAddress,
    		TransportUsername:   transportUsername,
    		TransportPassword:   transportPassword,
    
    Malte Bauch's avatar
    Malte Bauch committed
    		TransportOptionType: transportOptionType,
    
    		Model:               string(modelAsString),
    
    // MarshalBSON implements the MarshalBSON interface to store a network element as BSON.
    func (n *CommonNetworkElement) MarshalBSON() ([]byte, error) {
    
    	var transportType string
    	var transportAddress string
    	var transportUsername string
    	var transportPassword string
    	var transportOptionType spb.Type
    
    
    	// Handling of these cases is necessary as we use partial network elements for testing.
    
    	// eg. in most tests no transport or sbi is defined.
    	// The marshaller will crash if we want to access a nil field.
    
    	if n.transport == nil || n.transportOptions == nil {
    
    		transportType = "testing"
    		transportAddress = "testing"
    		transportUsername = "testing"
    		transportPassword = "testing"
    		transportOptionType = spb.Type_TYPE_OPENCONFIG
    	} else {
    
    		transportType = n.transport.Type()
    		transportAddress = n.transportOptions.Address
    		transportUsername = n.transportOptions.Username
    		transportPassword = n.transportOptions.Password
    		transportOptionType = n.transportOptions.Type
    
    	pluginUUID := n.Plugin.ID()
    
    
    Andre Sterba's avatar
    Andre Sterba committed
    	if err != nil {
    		return []byte{}, err
    	}
    
    
    		ID                  string   `bson:"_id,omitempty"`
    
    		Name                string   `bson:"name,omitempty"`
    		TransportType       string   `bson:"transport_type,omitempty"`
    		TransportAddress    string   `bson:"transport_address,omitempty"`
    		TransportUsername   string   `bson:"transport_username,omitempty"`
    		TransportPassword   string   `bson:"transport_password,omitempty"`
    		TransportOptionType spb.Type `bson:"transport_option"`
    
    		Plugin              string   `bson:"plugin,omitempty"`
    
    Andre Sterba's avatar
    Andre Sterba committed
    		Model               string   `bson:"model,omitempty"`
    
    		ID:                  n.ID().String(),
    		Name:                n.Name(),
    
    		TransportType:       transportType,
    		TransportAddress:    transportAddress,
    		TransportUsername:   transportUsername,
    		TransportPassword:   transportPassword,
    		TransportOptionType: transportOptionType,
    
    		Plugin:              pluginUUID.String(),
    
    Andre Sterba's avatar
    Andre Sterba committed
    		Model:               modelAsString,
    
    // GetModelAsString returns the YANG model of a network element as string.
    
    func (d *CommonNetworkElement) GetModelAsString() (string, error) {
    
    	byteModel, err := d.Plugin.Model()
    	return string(byteModel), err
    
    Malte Bauch's avatar
    Malte Bauch committed
    //TODO: check if this can be removed
    //func (n *CommonNetworkElement) getYgotEmitJSONConfig() *ygot.EmitJSONConfig {
    //	return &ygot.EmitJSONConfig{
    //		Format:         ygot.RFC7951,
    //		Indent:         "",
    //		SkipValidation: true,
    //		RFC7951Config: &ygot.RFC7951JSONConfig{
    //			AppendModuleName: true,
    //		}}
    //}