Newer
Older
package database
import (
"errors"
"github.com/neo4j/neo4j-go-driver/neo4j"
log "github.com/sirupsen/logrus"
)
type tapiDatabaseClient struct {
driver neo4j.Driver
}
//newTapiDatabaseClient creates a new tapiDatabaseClient with the given neo4j.Driver
func newTapiDatabaseClient(d neo4j.Driver) *tapiDatabaseClient {
return &tapiDatabaseClient{
driver: d,
}
}
//storeNodeTxFunc transaction to store devices from a json.
//relates them to a specific pnd id.
//returns a slice of added devices
func storeNodeTxFunc(id, name string, pndID int64) neo4j.TransactionWork {
return func(tx neo4j.Transaction) (interface{}, error) {
var nodelist []neo4j.Node
query :=
`
MERGE (device:Device {id: $id})
ON CREATE SET device.name = $name
WITH device
MATCH (pnd:PND)
MERGE (device)-[:BELONGS_TO]->(pnd)
RETURN device
`
result, err := tx.Run(query, map[string]interface{}{
"id": id,
"name": name,
})
if err != nil {
//TODO: handle neo4j.isServiceUnavailable()
return nil, err
}
for result.Next() {
nodelist = append(nodelist, result.Record().GetByIndex(0).(neo4j.Node))
}
if err = result.Err(); err != nil {
return nil, err
}
return nodelist, nil
}
}
//StoreNode 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 tapiDatabaseClient) storeNode(id, name string, pndID int64) ([]neo4j.Node, error) {
session := createSession(d.driver, true)
defer session.Close()
result, err := session.WriteTransaction(storeNodeTxFunc(id, name, pndID))
if err != nil {
log.Info(err)
}
log.Info("added/updated devices (count): ", len(result.([]neo4j.Node)))
return result.([]neo4j.Node), err
}
//storeLinkTxFunc transaction to store links from a json.
//creates relation between different devices.
//returns a slice of those created relations.
func storeLinkTxFunc(nep1Id, nep2Id string) neo4j.TransactionWork {
return func(tx neo4j.Transaction) (interface{}, error) {
var relationsList []neo4j.Relationship
query :=
`
MATCH (d:Device), (d2:Device)
WHERE d.id = $nep1Id
AND d2.id = $nep2Id
MERGE (d)-[r:connected]->(d2)
`
result, err := tx.Run(query, map[string]interface{}{
"nep1Id": nep1Id,
"nep2Id": nep2Id,
})
if err != nil {
//TODO: handle neo4j.isServiceUnavailable()
return nil, err
}
for result.Next() {
relationsList = append(relationsList, result.Record().GetByIndex(0).(neo4j.Relationship))
}
if err = result.Err(); err != nil {
return nil, err
}
return relationsList, nil
}
}
//StoreLink stores the links between nodes
func (d tapiDatabaseClient) storeLink(nep1Id, nep2Id string) ([]neo4j.Relationship, error) {
session := createSession(d.driver, true)
defer session.Close()
result, err := session.WriteTransaction(storeLinkTxFunc(nep1Id, nep2Id))
if err != nil {
log.Info(err)
}
log.Info("added/updated links (count): ", len(result.([]neo4j.Relationship)))
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
}
//storeNodeEdgePointsTxFunc transaction to store interfaces from a json.
//returns count of added/updated interfaces
func storeNodeEdgePointsTxFunc(json string) neo4j.TransactionWork {
return func(tx neo4j.Transaction) (interface{}, error) {
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`" + `
RETURN count(interface)
`
result, err := tx.Run(query, map[string]interface{}{
"stringToAdd": json,
})
if err != nil {
//TODO: handle neo4j.isServiceUnavailable()
return nil, err
}
if result.Next() {
return result.Record().GetByIndex(0), nil
}
return nil, errors.New("expected a record")
}
}
//TODO: currently this goes over each and every device/interface and adds
// a interface_of relation. -> do it only for the newly added interfaces
//storeNodeEdgePointsRelationTxFunc transaction to create relations between interfaces and devices
//returns count of added/updated relations
func storeNodeEdgePointsRelationTxFunc() neo4j.TransactionWork {
return func(tx neo4j.Transaction) (interface{}, error) {
query :=
`
MATCH (d:Device), (i:Interface)
WHERE d.id = i.` + "`containing-node`" + `
MERGE (i)-[r:INTERFACE_OF]->(d)
RETURN count(r)
`
result, err := tx.Run(query, nil)
if err != nil {
//TODO: handle neo4j.isServiceUnavailable()
return nil, err
}
if result.Next() {
return result.Record().GetByIndex(0), nil
}
return nil, errors.New("expected a record")
}
}
//StoreNodeEdgePoints stores the given node edge points (interfaces)
func (d tapiDatabaseClient) StoreNodeEdgePoints(json string) {
session := createSession(d.driver, true)
defer session.Close()
result, err := session.WriteTransaction(storeNodeEdgePointsTxFunc(json))
if err != nil {
log.Info(err)
}
_, err = session.WriteTransaction(storeNodeEdgePointsRelationTxFunc())
if err != nil {
log.Info(err)
}
log.Info("added/updated nodeEdgePoints (count): ", result)
}
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
//TODO: not implemented yet
//RemovePND removes the given principle network domain by id.
func (d tapiDatabaseClient) RemovePND(id string) {}
//GetPNDByID gets a specific PND by the given ID.
func (d tapiDatabaseClient) GetPNDByID(id string) {}
//GetNodesByLabel gets all nodes that belong to a specific label.
func (d tapiDatabaseClient) GetNodesByLabel(label string) {}
//GetNodeByID gets a specific node by ID.
func (d tapiDatabaseClient) GetNodeByID(id string) {}
//RemoveNodes removes the given nodes and their relationships
func (d tapiDatabaseClient) RemoveNodes(json string) {}
//RemoveSingleNode removes the given node and their relationship by id.
func (d tapiDatabaseClient) RemoveSingleNode(id string) {}
//StoreConnections stores relations between nodes
func (d tapiDatabaseClient) StoreConnections(json string) {}
//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() {}