Skip to content
Snippets Groups Projects
Commit 2aa93d64 authored by Andre Sterba's avatar Andre Sterba
Browse files

Add additional example application hostname-checker


See merge request !376

Co-authored-by: default avatarFabian Seidl <fabian.b.seidl@stud.h-da.de>
Co-authored-by: default avatarMalte Bauch <malte.bauch@tbnet.works>
parent 1ffce596
Branches
Tags
2 merge requests!382Develop,!376Add additional example application hostname-checker
Pipeline #116912 failed
......@@ -56,7 +56,7 @@ generate-csbi-yang-models: install-tools
../../$(TOOLS_DIR)/go-ygot-generator-generator config.yaml gostructs.go &&\
go generate
build: pre build-gosdn build-gosdnc build-orchestrator build-venv-manager build-arista-routing-engine-app
build: pre build-gosdn build-gosdnc build-orchestrator build-venv-manager build-arista-routing-engine-app build-hostname-checker-app
build-gosdn: pre
$(GOBUILD) -trimpath -o $(BUILD_ARTIFACTS_PATH)/gosdn ./controller/cmd/gosdn
......@@ -73,6 +73,9 @@ build-venv-manager: pre
build-arista-routing-engine-app: pre
$(GOBUILD) -trimpath -o $(BUILD_ARTIFACTS_PATH)/arista-routing-engine ./applications/arista-routing-engine
build-hostname-checker-app: pre
$(GOBUILD) -trimpath -o $(BUILD_ARTIFACTS_PATH)/hostname-checker ./applications/hostname-checker
containerize-all: containerize-gosdn containerize-gosdnc containerize-orchestrator containerize-target
containerize-gosdn:
......@@ -93,6 +96,9 @@ containerize-target:
containerize-arista-routing-engine-app:
docker buildx build --rm -t arista-routing-engine-app -f applications/arista-routing-engine/arista-routing-engine.Dockerfile .
containerize-hostname-checker-app:
docker buildx build --rm -t hostname-checker-app -f applications/hostname-checker/hostname-checker.Dockerfile .
containerlab-start: containerize-all
sudo containerlab deploy --topo gosdn.clab.yaml
......
package main
import (
"context"
"fmt"
"os"
"os/signal"
"syscall"
"time"
"code.fbi.h-da.de/danet/gosdn/api/go/gosdn/device"
"github.com/google/uuid"
"github.com/openconfig/ygot/ygot"
"code.fbi.h-da.de/danet/gosdn/application-framework/event"
"code.fbi.h-da.de/danet/gosdn/application-framework/models"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)
// Application is an example for a sdn application.
type Application struct {
eventService event.ServiceInterface
stopChannel chan os.Signal
grpcClientConn *grpc.ClientConn
}
// Run runs the application.
func (a *Application) Run() {
signal.Notify(a.stopChannel, os.Interrupt, syscall.SIGTERM)
a.eventService.SubscribeToEventType([]event.TypeToCallbackTuple{
{Type: event.Update, Callback: a.callback},
})
a.eventService.SetupEventReciever(a.stopChannel)
conn, err := grpc.Dial("localhost:55055", grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
panic(err)
}
a.grpcClientConn = conn
var forever chan struct{}
go func() {
for {
select {
case <-a.stopChannel:
close(forever)
_ = a.grpcClientConn.Close()
return
}
}
}()
<-forever
}
func (a *Application) callback(event *event.Event) {
ctx := context.Background()
deviceServer := device.NewDeviceServiceClient(a.grpcClientConn)
request := &device.GetDeviceRequest{
Timestamp: time.Now().UnixNano(),
DeviceID: event.EntityID.String(),
}
response, err := deviceServer.Get(ctx, request)
if err != nil {
fmt.Printf("Error %+v\n ", err)
return
}
fmt.Printf("\n[APP] Device-ID: %v, Device-Name: %+v \n", response.Device.Id, response.Device.Name)
d := NewDevice(uuid.MustParse(response.Device.Id), response.Device.Name)
// Create 'root' path to be able to load the whole model from the store.
path, err := ygot.StringToPath("/", ygot.StructuredPath)
if err != nil {
panic(err)
}
// Use unmarshall from the devices SBI to unmarshall ygot json in go struct.
err = models.Unmarshal([]byte(response.Device.Model), path, &d.Model)
if err != nil {
panic(err)
}
if *d.Model.System.Config.Hostname != d.Name {
fmt.Printf("[APP] Device.Name (%s) doesn't match Device.Hostname (%s) in model! Updating...\n",
d.Name,
*d.Model.System.Config.Hostname,
)
*d.Model.System.Config.Hostname = d.Name
modelAsString, err := models.GetModelAsString(&d.Model)
if err != nil {
panic(err)
}
requestUpdate := &device.UpdateDeviceRequest{
Timestamp: time.Now().UnixNano(),
Device: &device.Device{
Id: d.UUID.String(),
Name: d.Name,
Model: modelAsString,
},
}
updateResponse, err := deviceServer.Update(ctx, requestUpdate)
if err != nil {
panic(err)
}
fmt.Printf("[APP] Update response: %+v", updateResponse)
} else {
fmt.Printf("[APP] Device.Name (%s) does match Device.Hostname (%s) in model! Nothing to do for me...\n",
d.Name,
*d.Model.System.Config.Hostname,
)
}
}
package main
import (
"code.fbi.h-da.de/danet/gosdn/models/generated/arista"
"github.com/google/uuid"
)
// Device is a device.
type Device struct {
// UUID represents the Devices UUID
UUID uuid.UUID
// Name is the device's human readable Name
Name string
// Device embeds a ygot.GoStruct containing the device details
Model arista.Device
}
// NewDevice creates a new device.
func NewDevice(id uuid.UUID, name string) *Device {
return &Device{
UUID: id,
Model: arista.Device{},
Name: name,
}
}
package main
import (
"os"
"code.fbi.h-da.de/danet/gosdn/application-framework/event"
"code.fbi.h-da.de/danet/gosdn/application-framework/registration"
"github.com/sirupsen/logrus"
)
func main() {
queueCredentials, err := registration.Register("localhost:55055", "hostname-checker", "SecurePresharedToken")
if err != nil {
logrus.Errorf("failed to register application on control plane. %v", err)
os.Exit(1)
}
eventService, err := event.NewEventService(
queueCredentials,
[]event.Topic{event.Device},
)
if err != nil {
logrus.Errorf("failed to create event service. %v", err)
os.Exit(1)
}
app := &Application{
eventService: eventService,
stopChannel: make(chan os.Signal, 1),
}
app.Run()
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment