Skip to content
Snippets Groups Projects
database.go 6.84 KiB
Newer Older
  • Learn to ignore specific revisions
  • package database
    
    import (
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	"code.fbi.h-da.de/cocsn/gosdn/log"
    
    	"github.com/neo4j/neo4j-go-driver/neo4j"
    )
    
    
    //Database is a database
    
    type Database struct {
    
    Malte Bauch's avatar
    Malte Bauch committed
    	driver neo4j.Driver
    
    //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 {
    	driver := createDriver(uri, username, password, encrypted)
    
    	return Database{
    
    Malte Bauch's avatar
    Malte Bauch committed
    		driver: driver,
    
    	}
    
    }
    
    //createDriver creates a neo4j.Driver instance
    func createDriver(uri, username, password string, encrypted bool) neo4j.Driver {
    	driver, err := neo4j.NewDriver(
    		uri,
    		neo4j.BasicAuth(username, password, ""),
    		func(c *neo4j.Config) {
    			c.Encrypted = encrypted
    		},
    	)
    
    
    Malte Bauch's avatar
    Malte Bauch committed
    	if err != nil {
    
    Malte Bauch's avatar
    Malte Bauch committed
    		log.Info("failed creating database driver:", err)
    
    Malte Bauch's avatar
    Malte Bauch committed
    	}
    
    
    	return driver
    }
    
    //createSession creates a neo4j.Session
    
    Malte Bauch's avatar
    Malte Bauch committed
    func createSession(driver neo4j.Driver, write bool) neo4j.Session {
    	var sessionConfig neo4j.SessionConfig
    
    	if write {
    		sessionConfig = neo4j.SessionConfig{AccessMode: neo4j.AccessModeWrite}
    	} else {
    		sessionConfig = neo4j.SessionConfig{AccessMode: neo4j.AccessModeRead}
    	}
    
    
    	session, err := driver.NewSession(sessionConfig)
    
    
    Malte Bauch's avatar
    Malte Bauch committed
    	if err != nil {
    		log.Info("failed creating database session:", err)
    	}
    
    //StorePND stores the given principle network domain
    func (d Database) StorePND(pnd *PND) {
    
    Malte Bauch's avatar
    Malte Bauch committed
    	session := createSession(d.driver, true)
    	defer session.Close()
    
    
    	query :=
    		`
    		MERGE (pnd:PND {name: $name})
    		ON CREATE SET pnd.description = $description,
    			pnd.southboundInterfaces = $southboundInterfaces
    		`
    
    		//refactor map[string]interface... in own function
    
    Malte Bauch's avatar
    Malte Bauch committed
    	_, err := session.Run(
    
    		query, map[string]interface{}{
    			"name":                 pnd.name,
    			"description":          pnd.description,
    			"southboundInterfaces": pnd.southboundInterfaces,
    		})
    
    
    	if err != nil {
    		log.Info("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) {}
    
    Malte Bauch's avatar
    Malte Bauch committed
    func (d Database) GetPNDByID(id string) {}
    
    func (d Database) GetNodesByLabel(label string) {}
    
    func (d Database) GetDeviceByID(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 string) {
    	//TODO: remove this after testing and add own gRPC call for it
    	testPND := PND{name: "test_PND", description: "very, interesting", southboundInterfaces: []string{"TAPI", "RESTCONF"}}
    	d.StorePND(&testPND)
    
    
    Malte Bauch's avatar
    Malte Bauch committed
    	session := createSession(d.driver, true)
    	defer session.Close()
    
    
    	query :=
    		`
    		WITH apoc.convert.fromJsonMap($stringToAdd)
    		AS value
    		UNWIND value.data as d
    		MERGE (device:Device {id: d.object_id})
    
    		ON CREATE SET device.nativeName = d.object_data.` + "`tapi-object-data`.name[0].value," + `
    			device.deviceType = d.object_data.` + "`tapi-object-data`.name[1].value," + `
    			device.serialNumber = d.object_data.` + "`tapi-object-data`.name[2].value," + `
    			device.softwareVersion = d.object_data.` + "`tapi-object-data`.name[3].value," + `
    			device.` + "`operational-state` = d.object_data.`tapi-object-data`.`operational-state`" + `
    
    		WITH device
    		MATCH (pnd:PND)
    		WHERE pnd.name = $pnd
    		MERGE (device)-[:BELONGS_TO]->(pnd)
    		`
    
    Malte Bauch's avatar
    Malte Bauch committed
    	_, err := session.Run(
    
    		query, map[string]interface{}{
    			"stringToAdd": json,
    
    			"pnd":         testPND.name,
    
    Malte Bauch's avatar
    Malte Bauch committed
    	if err != nil {
    		log.Info("failed storing Nodes into database:", err)
    	}
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	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) {}
    
    
    //StoreLinks stores the links between nodes
    func (d Database) StoreLinks(json string) {
    
    Malte Bauch's avatar
    Malte Bauch committed
    	session := createSession(d.driver, true)
    	defer session.Close()
    
    
    	query :=
    
    Malte Bauch's avatar
    Malte Bauch committed
    		` WITH apoc.convert.fromJsonMap($stringToAdd)
    
    		AS value
    		UNWIND value.data as l
    		MATCH (d:Device), (d2:Device)
    		WHERE d.id = l.object_data.` + "`tapi-object-data`.`node-edge-point`[0].`node-uuid`" + `
    		AND d2.id = l.object_data.` + "`tapi-object-data`.`node-edge-point`[1].`node-uuid`" + `
    		CALL apoc.merge.relationship(d,l.object_data.` + "`tapi-object-data`.`layer-qualifier`,{},{}, d2,{})" + `
    		YIELD rel
    		RETURN rel
    		`
    
    
    Malte Bauch's avatar
    Malte Bauch committed
    	_, err := session.Run(
    
    		query, map[string]interface{}{
    			"stringToAdd": json,
    		})
    
    	if err != nil {
    		log.Info("failed storing Links into database:", err)
    	}
    
    	log.Info("successfully added Links into database")
    }
    
    
    //StoreNodeEdgePoints stores the given node edge points (interfaces)
    func (d Database) StoreNodeEdgePoints(json string) {
    
    Malte Bauch's avatar
    Malte Bauch committed
    	session := createSession(d.driver, true)
    	defer session.Close()
    
    
    	query :=
    
    		`
    		WITH apoc.convert.fromJsonMap($stringToAdd)
    		AS value
    		UNWIND value.data as i
    		MERGE (interface:Interface {id: i.object_id})
    		ON CREATE SET interface.object_type =i.object_type,
    
    		interface.localId = i.object_data.` + "`tapi-object-data`.name[0].value," + `
    		interface.location = i.object_data.` + "`tapi-object-data`.name[1].value," + `
    		interface.` + "`containing-node` = i.object_data.`tapi-object-data`.`containing-node`"
    
    Malte Bauch's avatar
    Malte Bauch committed
    	_, err := session.Run(
    
    		query, map[string]interface{}{
    
    Malte Bauch's avatar
    Malte Bauch committed
    	if err != nil {
    		log.Info("failed storing NodeEdgePoints into database:", err)
    	}
    
    Malte Bauch's avatar
    Malte Bauch committed
    	setNodeNodeEdgePointsRelation(session)
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	log.Info("successfully added NodeEdgePoints into database")
    
    //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) {
    	query :=
    		`
    		MATCH (d:Device), (i:Interface)
    		WHERE d.id = i.` + "`containing-node`" + `
    
    		MERGE (i)-[:INTERFACE_OF]->(d)
    
    		`
    
    	_, err := session.Run(
    		query, map[string]interface{}{})
    
    
    Malte Bauch's avatar
    Malte Bauch committed
    	if err != nil {
    		log.Info("failed storing NodeNodeEdgePointsRelation into database:", err)
    	}
    
    Manuel Kieweg's avatar
    Manuel Kieweg committed
    	log.Info("successfully stored NodeNodeEdgePointsRelation into database")
    
    Malte Bauch's avatar
    Malte Bauch committed
    //StoreTopology creates a new network topology node. Can also create a relation
    //the new node and a existing one if desired
    func StoreTopology() {}
    
    //RemoveTopology removes the given network topology. This includes the node itself
    //aswell as the containing links and relations
    func RemoveTopology() {}
    
    //CreateTopologyRelation creates a relation between two given topologies
    func CreateTopologyRelation() {}
    
    //CreateLink creates a link between two network elements
    func CreateLink() {}
    
    //RemoveLink removes a link between two network elements
    func RemoveLink() {}
    
    
    //Shutdown closes the connection to the database
    func (d Database) Shutdown() {
    	if err := d.driver.Close(); err != nil {
    	}