diff --git a/controller/interfaces/networkdomain/pnd.go b/controller/interfaces/networkdomain/pnd.go index 58e62256d28d95e4ef38add37b6d2257a1bc09da..8a943abe143c49e54a10aeffeec2531247a34141 100644 --- a/controller/interfaces/networkdomain/pnd.go +++ b/controller/interfaces/networkdomain/pnd.go @@ -16,7 +16,7 @@ type NetworkDomain interface { Destroy() error AddSbi(s southbound.SouthboundInterface) error RemoveSbi(uuid.UUID) error - AddNetworkElement(name string, opts *tpb.TransportOption, sid uuid.UUID) (uuid.UUID, error) + AddNetworkElement(name string, opts *tpb.TransportOption, sid uuid.UUID, networkElement uuid.UUID) (uuid.UUID, error) GetNetworkElement(identifier string) (networkelement.NetworkElement, error) RemoveNetworkElement(uuid.UUID) error UpdateNetworkElement(networkelement.NetworkElement, string) error diff --git a/controller/northbound/server/configurationmanagement.go b/controller/northbound/server/configurationmanagement.go index b5c38a13a426cb4b259596155b3e769293b55a56..09b7f5b1d1da81defa8ca0696cb37c836bd35ac4 100644 --- a/controller/northbound/server/configurationmanagement.go +++ b/controller/northbound/server/configurationmanagement.go @@ -6,14 +6,18 @@ import ( "time" cmpb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/configurationmanagement" + spb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/southbound" "code.fbi.h-da.de/danet/gosdn/controller/interfaces/networkdomain" "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/nucleus" "code.fbi.h-da.de/danet/gosdn/controller/store" "code.fbi.h-da.de/danet/gosdn/controller/topology" "code.fbi.h-da.de/danet/gosdn/controller/topology/links" "code.fbi.h-da.de/danet/gosdn/controller/topology/nodes" "code.fbi.h-da.de/danet/gosdn/controller/topology/ports" + + tpb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/transport" "github.com/google/uuid" ) @@ -30,7 +34,8 @@ type ConfigurationManagementServer struct { func NewConfigurationManagementServer( pndStore networkdomain.PndStore, topologyService topology.Service, - nodeService nodes.Service, portService ports.Service, + nodeService nodes.Service, + portService ports.Service, ) *ConfigurationManagementServer { return &ConfigurationManagementServer{ pndStore: pndStore, @@ -39,8 +44,8 @@ func NewConfigurationManagementServer( portService: portService} } -// SDNConfig is used to aprse the SDNConfig into JSON. -type SDNConfig struct { +// sdnConfig is used to parse the sdnConfig into JSON. +type sdnConfig struct { PndID string `json:"pndID"` Nodes []nodes.Node `json:"nodes"` Ports []ports.Port `json:"ports"` @@ -49,9 +54,19 @@ type SDNConfig struct { NetworkElements []networkelement.NetworkElement `json:"networkelements"` } +// loadedSDNConfig is used to parse the stringified JSON sdnConfig into objects. +type loadedSDNConfig struct { + PndID string `json:"pndID"` + Nodes []nodes.Node `json:"nodes"` + Ports []ports.Port `json:"ports"` + Links []links.Link `json:"links"` + Sbis []southbound.LoadedSbi `json:"sbis"` + NetworkElements []networkelement.LoadedNetworkElement `json:"networkelements"` +} + // ExportSDNConfig returns the SDN configuration. func (c ConfigurationManagementServer) ExportSDNConfig(ctx context.Context, request *cmpb.ExportSDNConfigRequest) (*cmpb.ExportSDNConfigResponse, error) { - var sdnConfig = SDNConfig{} + var sdnConfig = sdnConfig{} sdnConfig.PndID = request.Pid pndUUID := uuid.MustParse(request.Pid) @@ -91,7 +106,120 @@ func (c ConfigurationManagementServer) ExportSDNConfig(ctx context.Context, requ } // ImportSDNConfig receives an SDN configuration and imports it. -func (s *NetworkElementServer) ImportSDNConfig(ctx context.Context, request *cmpb.ImportSDNConfigRequest) (*cmpb.ImportSDNConfigResponse, error) { +func (c ConfigurationManagementServer) ImportSDNConfig(ctx context.Context, request *cmpb.ImportSDNConfigRequest) (*cmpb.ImportSDNConfigResponse, error) { + var sdnConfig = loadedSDNConfig{} + + err := json.Unmarshal([]byte(request.SdnConfigData), &sdnConfig) + if err != nil { + return nil, err + } + + //TODO: Clear DB + + //Create all elements + pndUUID := uuid.MustParse(request.Pid) + pnd, err := c.pndStore.Get(store.Query{ID: pndUUID}) + if err != nil { + return nil, err + } + + for _, inputSBI := range sdnConfig.Sbis { + sbi, err := nucleus.NewSBI(inputSBI.Type, uuid.MustParse(inputSBI.ID)) + if err != nil { + return nil, err + } + err = pnd.AddSbi(sbi) + if err != nil { + return nil, err + } + } + + for _, inputNode := range sdnConfig.Nodes { + node := nodes.Node{ + ID: inputNode.ID, + Name: inputNode.Name, + } + _, err = c.nodeService.EnsureExists(node) + if err != nil { + return nil, err + } + } + + for _, inputPort := range sdnConfig.Ports { + port := ports.Port{ + ID: inputPort.ID, + Name: inputPort.Name, + Configuration: inputPort.Configuration, + } + _, err = c.portService.EnsureExists(port) + if err != nil { + return nil, err + } + } + + for _, inputPort := range sdnConfig.Links { + sourceNode, err := c.nodeService.Get(store.Query{ID: inputPort.SourceNode.ID}) + if err != nil { + return nil, err + } + targetNode, err := c.nodeService.Get(store.Query{ID: inputPort.TargetNode.ID}) + if err != nil { + return nil, err + } + sourcePort, err := c.portService.Get(store.Query{ID: inputPort.SourcePort.ID}) + if err != nil { + return nil, err + } + targetPort, err := c.portService.Get(store.Query{ID: inputPort.TargetPort.ID}) + if err != nil { + return nil, err + } + link := links.Link{ + ID: inputPort.ID, + Name: inputPort.Name, + SourceNode: sourceNode, + TargetNode: targetNode, + SourcePort: sourcePort, + TargetPort: targetPort, + } + err = c.topologyService.AddLink(link) + if err != nil { + return nil, err + } + } + + for _, inputNetworkElement := range sdnConfig.NetworkElements { + transportOption := tpb.TransportOption{ + Address: inputNetworkElement.TransportAddress, + Username: inputNetworkElement.TransportUsername, + Password: inputNetworkElement.TransportPassword, + TransportOption: &tpb.TransportOption_GnmiTransportOption{ + GnmiTransportOption: &tpb.GnmiTransportOption{}, + }, + Type: spb.Type_TYPE_OPENCONFIG, + } + _, err := pnd.AddNetworkElement( + inputNetworkElement.Name, + &transportOption, + uuid.MustParse(inputNetworkElement.SBI), + uuid.MustParse(inputNetworkElement.ID), + ) + if err != nil { + return nil, err + } + + networkelement, err := pnd.GetNetworkElement(inputNetworkElement.ID) + if err != nil { + return nil, err + } + + err = pnd.UpdateNetworkElement(networkelement, inputNetworkElement.Model) + if err != nil { + return nil, err + } + + } + return &cmpb.ImportSDNConfigResponse{ Timestamp: time.Now().UnixNano()}, nil } diff --git a/controller/northbound/server/networkElement.go b/controller/northbound/server/networkElement.go index ebbb79d746e19817d3fb613d91a74ec70783bbf0..6aae6fe9bcb600f2d358cd61addeeea8eb719ff7 100644 --- a/controller/northbound/server/networkElement.go +++ b/controller/northbound/server/networkElement.go @@ -36,6 +36,7 @@ func (s *NetworkElementServer) Add(ctx context.Context, request *mnepb.AddNetwor request.NetworkElement.NetworkElementName, request.NetworkElement.TransportOption, sbiID, + uuid.Nil, ) if err != nil { return nil, status.Errorf(codes.Aborted, "%v", err) diff --git a/controller/northbound/server/pnd.go b/controller/northbound/server/pnd.go index 989f5f15ff53a2cf3af5aba11d1d4a4d2ac6c790..a623ed4f073424fe8edf2df524ced8a2f611860a 100644 --- a/controller/northbound/server/pnd.go +++ b/controller/northbound/server/pnd.go @@ -497,7 +497,7 @@ func (p PndServer) SetMneList(ctx context.Context, request *ppb.SetMneListReques log.Error(err) return nil, status.Errorf(codes.Aborted, "%v", err) } - mneID, err := pnd.AddNetworkElement(r.MneName, r.TransportOption, sid) + mneID, err := pnd.AddNetworkElement(r.MneName, r.TransportOption, sid, uuid.Nil) if err != nil { log.Error(err) return nil, status.Errorf(codes.Aborted, "%v", err) diff --git a/controller/nucleus/principalNetworkDomain.go b/controller/nucleus/principalNetworkDomain.go index 0b6d8b999353f80ae6dddc29176ac7722117d8cd..4e7d5d5068cc14fd1d79f829c301e6afd2357aa2 100644 --- a/controller/nucleus/principalNetworkDomain.go +++ b/controller/nucleus/principalNetworkDomain.go @@ -245,8 +245,8 @@ func (pnd *pndImplementation) RemoveSbi(sid uuid.UUID) error { return pnd.removeSbi(sid) } -// AddNetworkElement adds a new network element to the PND. -func (pnd *pndImplementation) AddNetworkElement(name string, opt *tpb.TransportOption, sid uuid.UUID) (uuid.UUID, error) { +// AddNetworkElement adds a new network element to the PND. The UUID for the networkElementID is optional and should normally be empty +func (pnd *pndImplementation) AddNetworkElement(name string, opt *tpb.TransportOption, sid uuid.UUID, networkElementID uuid.UUID) (uuid.UUID, error) { labels := prometheus.Labels{"type": opt.Type.String()} start := metrics.StartHook(labels, networkElementCreationsTotal) defer metrics.FinishHook(labels, start, networkElementCreationDurationSecondsTotal, networkElementCreationDurationSeconds) @@ -269,7 +269,7 @@ func (pnd *pndImplementation) AddNetworkElement(name string, opt *tpb.TransportO } } - mne, err := NewNetworkElement(name, uuid.Nil, opt, sbi, conflict.Metadata{ResourceVersion: 0}) + mne, err := NewNetworkElement(name, networkElementID, opt, sbi, conflict.Metadata{ResourceVersion: 0}) if err != nil { return uuid.Nil, err } diff --git a/controller/nucleus/principalNetworkDomain_test.go b/controller/nucleus/principalNetworkDomain_test.go index 38b704aac23a563aa6b703a2dd40965aa6bbeeff..f9650ef01a366e8bcb58e5cb2de7f0bbcfff8366 100644 --- a/controller/nucleus/principalNetworkDomain_test.go +++ b/controller/nucleus/principalNetworkDomain_test.go @@ -120,7 +120,7 @@ func Test_pndImplementation_AddNetworkElement(t *testing.T) { t.Error(err) } - _, err := pnd.AddNetworkElement(tt.args.name, tt.args.opts, defaultSbiID) + _, err := pnd.AddNetworkElement(tt.args.name, tt.args.opts, defaultSbiID, uuid.Nil) if (err != nil) != tt.wantErr { t.Errorf("AddNetworkElement() error = %v, wantErr %v", err, tt.wantErr) } @@ -469,11 +469,11 @@ func Test_pndImplementation_RemoveSbiWithAssociatedNetworkElements(t *testing.T) if err := pnd.addSbi(&OpenConfig{id: defaultSbiID}); err != nil { t.Error(err) } - _, err = pnd.AddNetworkElement("associatedNetworkElement", opts, tt.args.id) + _, err = pnd.AddNetworkElement("associatedNetworkElement", opts, tt.args.id, uuid.Nil) if err != nil { t.Error(err) } - _, err = pnd.AddNetworkElement("associatedNetworkElement2", opts, tt.args.id) + _, err = pnd.AddNetworkElement("associatedNetworkElement2", opts, tt.args.id, uuid.Nil) if err != nil { t.Error(err) } @@ -482,7 +482,7 @@ func Test_pndImplementation_RemoveSbiWithAssociatedNetworkElements(t *testing.T) if err := pnd.addSbi(&OpenConfig{id: newID}); err != nil { t.Error(err) } - _, err := pnd.AddNetworkElement("associatedNetworkElement2", opts, newID) + _, err := pnd.AddNetworkElement("associatedNetworkElement2", opts, newID, uuid.Nil) if err != nil { t.Error(err) } @@ -780,7 +780,7 @@ func Test_pndImplementation_ChangeMNE(t *testing.T) { if err := pnd.addSbi(&OpenConfig{id: defaultSbiID}); err != nil { t.Error(err) } - _, err := pnd.AddNetworkElement("testnetworkElement", opts, defaultSbiID) + _, err := pnd.AddNetworkElement("testnetworkElement", opts, defaultSbiID, uuid.Nil) if err != nil { t.Error(err) return diff --git a/controller/test/integration/nucleusIntegration_test.go b/controller/test/integration/nucleusIntegration_test.go index 62c56e8afd9d4b1a358767777c2cad8383e038ea..36e2cb291e545aa1a08d1bcc1431e0f63d0e9398 100644 --- a/controller/test/integration/nucleusIntegration_test.go +++ b/controller/test/integration/nucleusIntegration_test.go @@ -186,7 +186,7 @@ func TestGnmi_SetValidIntegration(t *testing.T) { t.Error(err) return } - _, err = pnd.AddNetworkElement("test", opt, sbi.ID()) + _, err = pnd.AddNetworkElement("test", opt, sbi.ID(), uuid.Nil) if err != nil { t.Error(err) return