From a62e29b8a46fe716f7d7bcab8818bfaf2c38d294 Mon Sep 17 00:00:00 2001
From: Malte Bauch <malte.bauch@stud.h-da.de>
Date: Tue, 29 Sep 2020 14:02:38 +0200
Subject: [PATCH] added principle network domain to database

Store nodes sets a relation between the nodes that are added and a
principle network domain.
---
 database/database.go            | 80 +++++++++++++++++++++++++++------
 restconf/client/ciena/client.go |  4 +-
 2 files changed, 68 insertions(+), 16 deletions(-)

diff --git a/database/database.go b/database/database.go
index caefc0974..461a1e878 100644
--- a/database/database.go
+++ b/database/database.go
@@ -5,16 +5,21 @@ import (
 	"github.com/neo4j/neo4j-go-driver/neo4j"
 )
 
-//Database
+//Database is a database
 type Database struct {
 	driver  neo4j.Driver
 	session neo4j.Session
 }
 
+//PND is a principle network domain
+type PND struct {
+	name                 string
+	description          string
+	southboundInterfaces []string
+}
+
 //NewDatabaseClient creates a database client
 func NewDatabaseClient(uri, username, password string, encrypted bool) Database {
-	//TODO: defer close()?
-	//		probably pretty nasty since it creates copies
 	driver := createDriver(uri, username, password, encrypted)
 	session := createSession(driver)
 
@@ -50,10 +55,35 @@ func createSession(driver neo4j.Driver) neo4j.Session {
 	return session
 }
 
-//StoreNodes stores the given nodes to the database
-func (d Database) StoreNodes(json string) {
-	session := d.session
+//StorePND stores the given principle network domain
+func (d Database) StorePND(pnd *PND) {
+	query :=
+		`
+		MERGE (pnd:PND {name: $name})
+		ON CREATE SET pnd.description = $description,
+			pnd.southboundInterfaces = $southboundInterfaces
+		`
+
+	_, err := d.session.Run(
+		query, map[string]interface{}{
+			"name":                 pnd.name,
+			"description":          pnd.description,
+			"southboundInterfaces": pnd.southboundInterfaces,
+		})
+
+	logError("failed storing PND into database", err)
+
+	log.Info("successfully added PND into database")
+}
+
+//RemovePND removes the given principle network domain by id.
+func (d Database) RemovePND(id string) {
+
+}
 
+//StoreNodes stores the given nodes to the database and adds them to a
+//principle networt domain (PND). It is required for a node to belong to a PND.
+func (d Database) StoreNodes(json, pndID string) {
 	query :=
 		`
 		WITH apoc.convert.fromJsonMap($stringToAdd)
@@ -64,11 +94,17 @@ func (d Database) StoreNodes(json string) {
 			device.deviceType = d.object_data.name[1].value,
 			device.serialNumber = d.object_data.name[2].value,
 			device.softwareVersion = d.object_data.name[3].value,
-			device.` + "`operational-state` = d.object_data.`operational-state`"
+			device.` + "`operational-state` = d.object_data.`operational-state`" + `
+		WITH device
+		MATCH (pnd:PND)
+		WHERE pnd.name = $pnd
+		MERGE (device)-[:BELONGS_TO]->(pnd)
+		`
 
-	_, err := session.Run(
+	_, err := d.session.Run(
 		query, map[string]interface{}{
 			"stringToAdd": json,
+			"pnd":         pndID,
 		})
 
 	logError("failed storing Nodes into database", err)
@@ -76,10 +112,14 @@ func (d Database) StoreNodes(json string) {
 	log.Info("successfully added Nodes into database")
 }
 
+//RemoveNodes removes the given nodes and their relationships
+func (d Database) RemoveNodes(json string) {}
+
+//RemoveSingleNode removes the given node and their relationship by id.
+func (d Database) RemoveSingleNode(id string) {}
+
 //StoreNodeEdgePoints stores the given node edge points (interfaces)
 func (d Database) StoreNodeEdgePoints(json string) {
-	session := d.session
-
 	queryEdgePoints :=
 		`
 		WITH apoc.convert.fromJsonMap($stringToAdd)
@@ -91,20 +131,21 @@ func (d Database) StoreNodeEdgePoints(json string) {
 		interface.location = i.object_data.name[1].value,
 		interface.` + "`containing-node` = i.object_data.`containing-node`"
 
-	_, err := session.Run(
+	_, err := d.session.Run(
 		queryEdgePoints, map[string]interface{}{
 			"stringToAdd": json,
 		})
 
 	logError("failed storing NodeEdgePoints into database", err)
 
-	setNodeNodeEdgePointsRelation(session)
+	setNodeNodeEdgePointsRelation(d.session)
 
 	log.Info("successfully added NodeEdgePoints into database")
 
 }
 
-func (d Database) StoreConnections(json string){}
+//StoreConnections stores relations between nodes
+func (d Database) StoreConnections(json string) {}
 
 //setNodeNodeEdgePointsRelation creates the database relations between "nodes" and "node edge points"
 func setNodeNodeEdgePointsRelation(session neo4j.Session) {
@@ -112,7 +153,7 @@ func setNodeNodeEdgePointsRelation(session neo4j.Session) {
 		`
 		MATCH (d:Device), (i:Interface)
 		WHERE d.id = i.` + "`containing-node`" + `
-		CREATE (i)-[:BELONGS_TO]->(d)
+		MERGE (i)-[:INTERFACE_OF]->(d)
 		`
 
 	_, err := session.Run(
@@ -123,6 +164,17 @@ func setNodeNodeEdgePointsRelation(session neo4j.Session) {
 	log.Info("successfully stored NodeNodeEdgePointsRelation into database")
 }
 
+//Shutdown closes the connection to the database
+func (d Database) Shutdown() {
+	//TODO: add logger
+	if err := d.session.Close(); err != nil {
+	}
+
+	if err := d.driver.Close(); err != nil {
+	}
+
+}
+
 //logError logs error with custom and error message
 func logError(message string, err error) {
 	if err != nil {
diff --git a/restconf/client/ciena/client.go b/restconf/client/ciena/client.go
index cb514e37a..1dea66548 100644
--- a/restconf/client/ciena/client.go
+++ b/restconf/client/ciena/client.go
@@ -57,10 +57,10 @@ func (c *MCPClient) GetConnections() error {
 	return err
 }
 
-func (c *MCPClient) GetNodes() error {
+func (c *MCPClient) GetNodes(pndName string) error {
 	defer c.buffer.Reset()
 	_, err := c.client.TapiTopologyCore.GetTapiCoreContextTopologyMcpBaseTopologyNode(nil)
-	c.database.StoreNodes(c.buffer.String())
+	c.database.StoreNodes(c.buffer.String(), pndName)
 	log.Debug(c.buffer.Next(25))
 	return err
 }
-- 
GitLab