Skip to content
Snippets Groups Projects
Verified Commit 2522a192 authored by André Sterba's avatar André Sterba
Browse files

Remove plugin interfaces and move to ports and model

parent 17f66f35
No related branches found
No related tags found
1 merge request!557Draft: Refactor nucleus to remove hard dependencies on structs
Pipeline #163361 failed
package plugin
import (
"encoding/json"
"fmt"
"net"
"os"
"path/filepath"
"regexp"
"code.fbi.h-da.de/danet/gosdn/controller/customerrs"
"code.fbi.h-da.de/danet/gosdn/controller/nucleus/util"
"code.fbi.h-da.de/danet/gosdn/controller/plugin/shared"
"github.com/google/uuid"
hcplugin "github.com/hashicorp/go-plugin"
"go.mongodb.org/mongo-driver/bson"
"gopkg.in/yaml.v3"
)
// State represents the current state of a plugin within the controller. Since
// the plugins used within the controller are basic go plugins, they can be
// CREATED, BUILT, LOADED or FAULTY. A plugin can not be unloaded (this is a
// limitation of go plugins in general).
type State int64
const (
//CREATED state describes a plugin which has been created but is not yet
//built.
CREATED State = iota
// INITIALIZED state describes a plugin which is running and has been
// initialized with the model data of the associated network element.
INITIALIZED
// FAULTY state describes a plugin which couldn't be built or loaded.
FAULTY
)
// Plugin describes an interface for a plugin within the controller. A plugin
// is based on hashicorp's `go plugin`.
type Plugin interface {
ID() uuid.UUID
GetClient() *hcplugin.Client
State() State
Manifest() *Manifest
ExecPath() string
Update() error
Ping() error
Restart() error
Close()
shared.DeviceModel
}
// Manifest represents the manifest of a plugin.
type Manifest struct {
// Name of the plugin
Name string `yaml:"name" json:"name" bson:"name"`
// Name of the plugin
Firmware string `yaml:"firmware" json:"firmware" bson:"firmware"`
// Author of the plugin
Author string `yaml:"author" json:"author" bson:"author"`
// Version of the plugin
Version string `yaml:"version" json:"version" bson:"version"`
}
// Validate is a method to check if the manifest is valid and is compliant with
// the requirements.
func (m *Manifest) Validate() error {
errs := []error{}
if m.Name == "" {
errs = append(errs, fmt.Errorf("Name is required"))
}
if m.Firmware == "" {
errs = append(errs, fmt.Errorf("Firmware is required"))
}
if m.Author == "" {
errs = append(errs, fmt.Errorf("Author is required"))
}
if m.Version == "" {
errs = append(errs, fmt.Errorf("Version is required"))
}
// regex from: https://stackoverflow.com/a/68921827
validVersion, err := regexp.MatchString(`^([1-9]\d*|0)(\.(([1-9]\d*)|0)){2}$`,
m.Version)
if err != nil {
errs = append(errs, err)
}
if !validVersion {
errs = append(errs, fmt.Errorf("Version has to be of form: X.X.X"))
}
if len(errs) != 0 {
return customerrs.CombinedErrListError{Errors: errs}
}
return nil
}
// ReadManifestFromFile reads a manifest file and returns a pointer to a newly
// created Manifest.
func ReadManifestFromFile(path string) (*Manifest, error) {
manifest := &Manifest{}
manifestFile, err := os.ReadFile(filepath.Join(path, util.ManifestFileName))
if err != nil {
return nil, err
}
err = yaml.Unmarshal(manifestFile, manifest)
if err != nil {
return nil, err
}
// validate the loaded manifest
if err := manifest.Validate(); err != nil {
return nil, err
}
return manifest, nil
}
type LoadedPlugin struct {
// ID represents the UUID of the LoadedPlugin.
ID string `json:"id" bson:"_id"`
// Manifest represents the manifest of the LoadedPlugin.
Manifest Manifest `json:"manifest" bson:"manifest"`
// State represents the state of the LoadedPlugin.
State State `json:"state,omitempty" bson:"state"`
// ExecPath represents the path to the executable of the plugin.
ExecPath string `json:"exec_path,omitempty" bson:"exec_path"`
// ReattachConfig represents the configuration to reattach to a already
// running plugin.
ReattachConfig hcplugin.ReattachConfig `json:"reattatch_config,omitempty" bson:"reattatch_config"`
}
func (lp *LoadedPlugin) UnmarshalBSON(data []byte) error {
loadedPluginHelper := new(LoadedPluginHelper)
if err := bson.Unmarshal(data, loadedPluginHelper); err != nil {
return err
}
lp.ID = loadedPluginHelper.ID
lp.Manifest = loadedPluginHelper.Manifest
lp.State = loadedPluginHelper.State
lp.ExecPath = loadedPluginHelper.ExecPath
lp.ReattachConfig = hcplugin.ReattachConfig{
Protocol: hcplugin.Protocol(loadedPluginHelper.ReattachConfig.Protocol),
ProtocolVersion: loadedPluginHelper.ReattachConfig.ProtocolVersion,
Addr: &net.UnixAddr{
Name: loadedPluginHelper.ReattachConfig.Addr.Name,
Net: loadedPluginHelper.ReattachConfig.Addr.Net,
},
Pid: loadedPluginHelper.ReattachConfig.Pid,
Test: loadedPluginHelper.ReattachConfig.Test,
}
return nil
}
func (lp *LoadedPlugin) UnmarshalJSON(data []byte) error {
loadedPluginHelper := new(LoadedPluginHelper)
if err := json.Unmarshal(data, loadedPluginHelper); err != nil {
return err
}
lp.ID = loadedPluginHelper.ID
lp.Manifest = loadedPluginHelper.Manifest
lp.State = loadedPluginHelper.State
lp.ExecPath = loadedPluginHelper.ExecPath
lp.ReattachConfig = hcplugin.ReattachConfig{
Protocol: hcplugin.Protocol(loadedPluginHelper.ReattachConfig.Protocol),
ProtocolVersion: loadedPluginHelper.ReattachConfig.ProtocolVersion,
Addr: &net.UnixAddr{
Name: loadedPluginHelper.ReattachConfig.Addr.Name,
Net: loadedPluginHelper.ReattachConfig.Addr.Net,
},
Pid: loadedPluginHelper.ReattachConfig.Pid,
Test: loadedPluginHelper.ReattachConfig.Test,
}
return nil
}
type LoadedPluginHelper struct {
ID string `json:"id" bson:"_id"`
Manifest Manifest `json:"manifest" bson:"manifest"`
State State `json:"state,omitempty" bson:"state"`
ExecPath string `json:"exec_path,omitempty" bson:"exec_path"`
ReattachConfig LoadedReattachConfig `json:"reattatch_config,omitempty" bson:"reattatch_config"`
}
type LoadedReattachConfig struct {
Protocol string
ProtocolVersion int
Addr LoadedAddress
Pid int
Test bool
}
type LoadedAddress struct {
Name string
Net string
}
package plugin
// // Service describes an interface for plugin service implementations.
// type Service interface {
// Add(Plugin) error
// Delete(Plugin) error
// Get(model.Query) (Plugin, error)
// GetAll() ([]Plugin, error)
// RequestPlugin(uuid.UUID) (Plugin, error)
// }
package plugin
// // Store describes an interface for plugin store implementations.
// type Store interface {
// Add(Plugin) error
// Update(Plugin) error
// Delete(Plugin) error
// Get(model.Query) (LoadedPlugin, error)
// GetAll() ([]LoadedPlugin, error)
// }
......@@ -9,7 +9,6 @@ import (
spb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/southbound"
tpb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/transport"
"code.fbi.h-da.de/danet/gosdn/controller/conflict"
"code.fbi.h-da.de/danet/gosdn/controller/interfaces/plugin"
"code.fbi.h-da.de/danet/gosdn/controller/nucleus/domain/model"
"code.fbi.h-da.de/danet/gosdn/controller/nucleus/domain/ports"
"code.fbi.h-da.de/danet/gosdn/controller/topology"
......@@ -62,7 +61,7 @@ type sdnConfig struct {
Nodes []nodes.Node `json:"nodes"`
Ports []topoPorts.Port `json:"ports"`
Links []links.Link `json:"links"`
Plugins []plugin.LoadedPlugin `json:"plugins"`
Plugins []model.LoadedPlugin `json:"plugins"`
NetworkElements []model.NetworkElement `json:"networkelements"`
}
......@@ -72,12 +71,15 @@ type loadedSDNConfig struct {
Nodes []nodes.Node `json:"nodes"`
Ports []topoPorts.Port `json:"ports"`
Links []links.Link `json:"links"`
Plugins []plugin.LoadedPlugin `json:"plugins"`
Plugins []model.LoadedPlugin `json:"plugins"`
NetworkElements []model.LoadedNetworkElement `json:"networkelements"`
}
// ExportSDNConfig returns the SDN configuration.
func (c ConfigurationManagementServer) ExportSDNConfig(ctx context.Context, request *cmpb.ExportSDNConfigRequest) (*cmpb.ExportSDNConfigResponse, error) {
func (c ConfigurationManagementServer) ExportSDNConfig(
ctx context.Context,
request *cmpb.ExportSDNConfigRequest,
) (*cmpb.ExportSDNConfigResponse, error) {
if err := c.protoValidator.Validate(request); err != nil {
return nil, status.Errorf(codes.Aborted, "%v", err)
}
......
......@@ -7,10 +7,10 @@ import (
"os"
"os/exec"
"path/filepath"
"plugin"
"regexp"
"code.fbi.h-da.de/danet/gosdn/controller/customerrs"
"code.fbi.h-da.de/danet/gosdn/controller/interfaces/plugin"
"code.fbi.h-da.de/danet/gosdn/controller/nucleus/util"
"code.fbi.h-da.de/danet/gosdn/controller/plugin/shared"
"github.com/google/uuid"
......
......@@ -8,7 +8,7 @@ import (
"path/filepath"
pb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/plugin-registry"
"code.fbi.h-da.de/danet/gosdn/controller/interfaces/plugin"
"code.fbi.h-da.de/danet/gosdn/controller/nucleus/domain/model"
"github.com/google/uuid"
"google.golang.org/grpc"
)
......@@ -52,7 +52,7 @@ func registerPlugins() *PluginRegistry {
fmt.Printf("File %+v\n", file)
if file.IsDir() {
manifest, err := plugin.ReadManifestFromFile(filepath.Join(pluginFilePath, file.Name()))
manifest, err := model.ReadManifestFromFile(filepath.Join(pluginFilePath, file.Name()))
if err != nil {
panic(err)
}
......
......@@ -4,14 +4,14 @@ import (
"fmt"
pb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/plugin-registry"
"code.fbi.h-da.de/danet/gosdn/controller/interfaces/plugin"
"code.fbi.h-da.de/danet/gosdn/controller/nucleus/domain/model"
"github.com/google/uuid"
)
type Plugin struct {
ID uuid.UUID `json:"id,omitempty"`
Path string `json:"path,omitempty"`
Manifest *plugin.Manifest `json:"manifest,omitempty"`
ID uuid.UUID `json:"id,omitempty"`
Path string `json:"path,omitempty"`
Manifest *model.Manifest `json:"manifest,omitempty"`
}
type PluginRegistry struct {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment