Skip to content
Snippets Groups Projects
Commit 5bb90249 authored by Malte Bauch's avatar Malte Bauch
Browse files

Merge branch 'develop' into 13-neo4j-2

parents 10929794 7f97a0a7
No related branches found
No related tags found
2 merge requests!43Resolve "neo4j",!18Develop
Pipeline #52599 passed with warnings
......@@ -12,35 +12,34 @@ before_script:
code-quality-master:
image: golangci/golangci-lint:latest-alpine
stage: test
only:
- merge_requests
except:
variables:
- $CI_MERGE_REQUEST_TARGET_BRANCH_NAME != "master"
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
when: manual
script:
- git config --global url."https://$GO_MODULES_USER:$GO_MODULES_ACCESS_TOKEN@code.fbi.h-da.de".insteadOf "https://code.fbi.h-da.de"
# writes golangci-lint output to gl-code-quality-report.json
- golangci-lint run --config .ci/.golangci-master.yml | tee gl-code-quality-report.json
- golangci-lint run --config .ci/.golangci-master.yml --out-format code-climate | tee gl-code-quality-report.json
artifacts:
reports:
codequality: gl-code-quality-report.json
paths:
- gl-code-quality-report.json
code-quality:
image: golangci/golangci-lint:latest-alpine
stage: test
allow_failure: true
only:
- merge_requests
except:
variables:
- $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME != $CI_DEFAULT_BRANCH
script:
# writes golangci-lint output to gl-code-quality-report.json
- golangci-lint run --config .ci/.golangci.yml | tee gl-code-quality-report.json
- golangci-lint run --config .ci/.golangci.yml--out-format code-climate | tee gl-code-quality-report.json
artifacts:
reports:
codequality: gl-code-quality-report.json
paths:
- gl-code-quality-report.json
Documentation:
before_script:
......@@ -50,9 +49,9 @@ Documentation:
entrypoint:
- ''
stage: build
only:
changes:
- documentation/design/*.md
rules:
- changes:
- documentation/design/*.md
script:
- cd documentation/design
- pandoc --filter pandoc-citeproc --bibliography=bibliography.bib --csl=acm-sig-proceedings.csl
......@@ -78,4 +77,3 @@ include:
- template: Security/SAST.gitlab-ci.yml
- template: Dependency-Scanning.gitlab-ci.yml
- template: Security/License-Scanning.gitlab-ci.yml
[[client]]
identifier = "ciena-mcp"
endpoint = "141.100.70.170:8080"
\ No newline at end of file
......@@ -3,7 +3,12 @@ package log
import (
"fmt"
"io"
"log/syslog"
"os"
"reflect"
"runtime"
"strconv"
"strings"
"sync"
"time"
)
......@@ -14,22 +19,47 @@ var once sync.Once
// Logger is a wrapper for log.Logger and provides
// methods to enable and disable logging.
type Logger struct {
Out io.Writer
Loglevel Level
lock sync.Mutex
DefaultWriter io.Writer
LoglevelWriter map[Level]io.Writer
toSyslog map[Level]bool
Loglevel Level
lock sync.Mutex
builder strings.Builder
}
func (l *Logger) buildMessage(level Level, syslog bool, args ...interface{}) {
if !syslog {
l.builder.WriteString(time.Now().Format(time.RFC3339))
}
l.builder.WriteRune('\t')
l.builder.WriteString(prefix(level))
l.builder.WriteRune('\t')
function, line := callers()
functionSplitted := strings.SplitAfter(function, "/")
function = functionSplitted[len(functionSplitted)-1]
l.builder.WriteString(function)
l.builder.WriteRune(':')
l.builder.WriteString(strconv.Itoa(line))
l.builder.WriteRune('\t')
l.builder.WriteString(fmt.Sprint(args...))
l.builder.WriteRune('\n')
}
func get() *Logger {
once.Do(func() {
logger = &Logger{
Out: os.Stdout,
Loglevel: INFO,
lock: sync.Mutex{},
DefaultWriter: os.Stderr,
LoglevelWriter: make(map[Level]io.Writer),
toSyslog: make(map[Level]bool),
Loglevel: INFO,
lock: sync.Mutex{},
}
})
return logger
}
//Loglevel sets the verbosity of the logger
//Defaults to INFO
func Loglevel(level Level) {
l := get()
l.lock.Lock()
......@@ -37,48 +67,101 @@ func Loglevel(level Level) {
l.Loglevel = level
}
//Output defines the output of the logger
//Defaults to os.Stderr
func Output(out io.Writer) {
l := get()
l.lock.Lock()
defer l.lock.Unlock()
l.Out = out
l.DefaultWriter = out
}
//LoglevelOutput defines a special output
//for a certain log level
func LoglevelOutput(level Level, out io.Writer) {
l := get()
l.lock.Lock()
defer l.lock.Unlock()
l.LoglevelWriter[level] = out
if reflect.TypeOf(out) == reflect.TypeOf(&syslog.Writer{}) {
l.toSyslog[level] = true
}
}
//Debug passes the DEBUG flag and a
//message to the logger
func Debug(args ...interface{}) {
log(DEBUG, args...)
}
//Debug passes the DEBUG flag and a
//message to the logger
func Info(args ...interface{}) {
log(INFO, args...)
}
//Warn passes the WARNING flag and a
//message to the logger
func Warn(args ...interface{}) {
log(WARNING, args...)
}
//Error passes the ERROR flag and a
//message to the logger
func Error(args ...interface{}) {
log(ERROR, args...)
}
//Fatal passes the FATAL flag and a
//message to the logger and calls
//os.Exit(1)
func Fatal(args ...interface{}) {
log(FATAL, args...)
os.Exit(1)
}
//Panic passes the PANIC flag and a
//message to the logger
//Also calls builtin.panic()
func Panic(args ...interface{}) {
log(PANIC, args...)
panic(args)
}
func log(level Level, args ...interface{}) {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered in f", r)
}
}()
l := get()
l.lock.Lock()
defer l.lock.Unlock()
defer l.builder.Reset()
if level <= l.Loglevel {
msg := fmt.Sprint(args...)
logMessage := time.Now().Format(time.RFC3339) + "\t" + prefix(level) + "\t" + msg + "\n"
l.Out.Write([]byte(logMessage))
l.buildMessage(level, l.toSyslog[level], args...)
msg := []byte(l.builder.String())
writer, ok := l.LoglevelWriter[level]
var err error
if !ok {
_, err = l.DefaultWriter.Write(msg)
} else {
_, err = writer.Write(msg)
}
if err != nil {
panic(err)
}
}
}
func callers() (string, int) {
pc := make([]uintptr, 15)
n := runtime.Callers(5, pc)
frames := runtime.CallersFrames(pc[:n])
frame, _ := frames.Next()
return frame.Function, frame.Line
}
func prefix(level Level) string {
switch level {
case PANIC:
......
......@@ -4,6 +4,7 @@ import (
"code.fbi.h-da.de/cocsn/gosdn/log"
"code.fbi.h-da.de/cocsn/gosdn/nucleus"
"flag"
"log/syslog"
)
func main() {
......@@ -17,6 +18,16 @@ func main() {
cliSocket := *cliListenAddr + ":" + *cliListenPort
log.Loglevel(log.DEBUG)
syslogWriter, err := syslog.New(syslog.LOG_ALERT, "gosdn")
defer func() {
if err := syslogWriter.Close(); err != nil {
log.Fatal(err)
}
}()
if err != nil {
log.Fatal(err)
}
log.LoglevelOutput(log.INFO, syslogWriter)
// Setup a channel to communicate if goSDN should shutdown.
IsRunningChannel := make(chan bool)
......
......@@ -18,6 +18,10 @@ type controllerConfig struct {
ConfigPath string
}
type clientConfigs struct {
Client []interfaces.ClientConfig `toml:"client"`
}
type Core struct {
//Assert type with clients[key].(*MCPClient)
clients map[string]interfaces.Client
......@@ -26,33 +30,22 @@ type Core struct {
IsRunning chan bool
}
func (c *Core) Init(socket, configfile string, IsRunningChannel chan bool) {
if configfile == "" {
configfile = "gosdn.toml"
}
_, err := os.Stat(configfile)
if err != nil {
log.Fatal("Config file is missing: ", configfile)
}
c.config = controllerConfig{}
if _, err := toml.DecodeFile(configfile, &c.config); err != nil {
func (c *Core) Init(socket, configFileController, configFileClient string, IsRunningChannel chan bool) {
if err := c.readControllerConfig(configFileController); err != nil {
log.Fatal(err)
}
if socket != "localhost:55055" {
c.config.CliSocket = socket
}
if c.config.ConfigPath == "" {
c.config.ConfigPath = configfile
}
c.AttachDatabase()
c.IsRunning = IsRunningChannel
//TODO: Create client config/CLI adapter
c.clients["ciena-mcp"] = ciena.NewMCPClient("141.100.70.170:8080", "", "", &c.database)
if err := c.readClientConfig(configFileClient); err != nil {
log.Fatal(err)
}
}
func (c *Core) AttachDatabase() {
......@@ -61,13 +54,8 @@ func (c *Core) AttachDatabase() {
func (c *Core) Shutdown() {
stopIt := <- c.IsRunning
if !stopIt {
log.Debug("Shutdown() received action to shutdown")
}else {
log.Debug("Shutdown() received something else.")
}
<- c.IsRunning
log.Info("Received shutdown signal. Shutting down")
f, err := os.Create(c.config.ConfigPath)
if err != nil {
......@@ -77,6 +65,42 @@ func (c *Core) Shutdown() {
if err := enc.Encode(c.config); err != nil {
log.Fatal(err)
}
log.Info("Shutdown complete")
os.Exit(0)
}
func (c *Core)readControllerConfig(configFileController string) error {
if configFileController == "" {
configFileController = "gosdn.toml"
}
if _, err := os.Stat(configFileController); err != nil {
return err
}
c.config = controllerConfig{}
if _, err := toml.DecodeFile(configFileController, &c.config); err != nil {
return err
}
if c.config.ConfigPath == "" {
c.config.ConfigPath = configFileController
}
return nil
}
func (c *Core)readClientConfig(configFileClient string) error {
if configFileClient == "" {
configFileClient = "clients.toml"
}
if _,err := os.Stat(configFileClient); err != nil {
return err
}
clients := clientConfigs{}
if _,err := toml.DecodeFile(configFileClient, &clients); err != nil {
return err
}
for _,client := range clients.Client {
c.clients[client.Identifier] = ciena.NewMCPClient(client.Endpoint, client.Username, client.Password, &c.database, &client)
}
return nil
}
\ No newline at end of file
package interfaces
type Client interface {
GetConfig() string
GetConfig() ClientConfig
}
package interfaces
type ClientConfig struct {
Identifier string `toml:"identifier"`
Endpoint string `toml:"endpoint"`
Username string `toml:"username"`
Password string `toml:"password"`
}
......@@ -7,10 +7,7 @@ import (
"time"
)
/*
* This function is used to start the core of the controller and any auxiliary services.
*/
//StartAndRun is used to start the core of the controller and any auxiliary services.
func StartAndRun(socket, filename string, IsRunningChannel chan bool) {
log.Info("This is the network superintendent...")
log.Info("Starting my ducks")
......@@ -20,7 +17,7 @@ func StartAndRun(socket, filename string, IsRunningChannel chan bool) {
clients: make(map[string]interfaces.Client),
database: database.Database{},
}
core.Init(socket, filename, IsRunningChannel)
core.Init(socket, filename,"", IsRunningChannel)
// Start the GRCP CLI
go getCLIGoing(&core)
go core.Shutdown()
......@@ -28,10 +25,8 @@ func StartAndRun(socket, filename string, IsRunningChannel chan bool) {
log.Info("and ready for take off")
//Just to produce some signs of vitality...
for (true) {
for {
time.Sleep(10 * time.Second)
log.Debug("Still alive...")
}
log.Info("Good bye....!")
}
......@@ -4,6 +4,7 @@ import (
"bytes"
"code.fbi.h-da.de/cocsn/gosdn/database"
"code.fbi.h-da.de/cocsn/gosdn/log"
"code.fbi.h-da.de/cocsn/gosdn/nucleus/interfaces"
"code.fbi.h-da.de/cocsn/gosdn/restconf/util"
apiclient "code.fbi.h-da.de/cocsn/swagger/apis/mcp/client"
"crypto/tls"
......@@ -19,15 +20,15 @@ type MCPClient struct {
client *apiclient.ServiceTopologyTAPI
database *database.Database
buffer *bytes.Buffer
config *interfaces.ClientConfig
}
func (c MCPClient) GetConfig() string {
//TODO: Fill with life
return "..."
func (c MCPClient) GetConfig() interfaces.ClientConfig {
return *c.config
}
//NewMCPClient creates a client
func NewMCPClient(endpoint, username, password string, database *database.Database) *MCPClient {
func NewMCPClient(endpoint, username, password string, database *database.Database, config *interfaces.ClientConfig) *MCPClient {
// create the transport
transport := httptransport.New(endpoint, "/", nil)
transport.Transport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
......@@ -45,6 +46,7 @@ func NewMCPClient(endpoint, username, password string, database *database.Databa
client: client,
database: database,
buffer: buffer,
config: config,
}
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment