mirror of
https://github.com/vxcontrol/vxcommon.git
synced 2026-07-20 09:34:35 -04:00
221 lines
6.1 KiB
Go
221 lines
6.1 KiB
Go
package loader
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"sync"
|
|
|
|
"github.com/vxcontrol/luar"
|
|
"github.com/vxcontrol/vxcommon/agent"
|
|
"github.com/vxcontrol/vxcommon/lua"
|
|
"github.com/vxcontrol/vxcommon/vxproto"
|
|
)
|
|
|
|
type deferredModuleCallback func() bool
|
|
|
|
// ModuleState is struct for contains information about module
|
|
type ModuleState struct {
|
|
name string
|
|
item *ModuleItem
|
|
status agent.ModuleStatus_Status
|
|
wg sync.WaitGroup
|
|
luaModule *lua.Module
|
|
luaState *lua.State
|
|
cbStart deferredModuleCallback
|
|
cbStop deferredModuleCallback
|
|
}
|
|
|
|
// NewState is function which constructed ModuleState object
|
|
func NewState(mc *ModuleConfig, mi *ModuleItem, p vxproto.IVXProto) (*ModuleState, error) {
|
|
ms := &ModuleState{
|
|
name: mc.Name,
|
|
item: mi,
|
|
status: agent.ModuleStatus_UNKNOWN,
|
|
}
|
|
|
|
socket := p.NewModule(ms.name, mc.AgentID)
|
|
if socket == nil {
|
|
return nil, errors.New("module socket for " + ms.name + " not initialized")
|
|
}
|
|
ms.cbStart = func() bool {
|
|
agents := make(map[string]*vxproto.AgentInfo)
|
|
for dst, info := range p.GetAgentList() {
|
|
if mc.AgentID == "" || info.ID == mc.AgentID {
|
|
agents[dst] = info
|
|
}
|
|
}
|
|
ms.luaModule.SetAgents(agents)
|
|
|
|
if !p.AddModule(socket) {
|
|
socket.Close()
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
ms.cbStop = func() bool {
|
|
ms.luaModule.SetAgents(make(map[string]*vxproto.AgentInfo))
|
|
return p.DelModule(socket)
|
|
}
|
|
|
|
var err error
|
|
if ms.luaState, err = lua.NewState(mi.files); err != nil {
|
|
return nil, errors.New("error with creating new state: " + err.Error())
|
|
}
|
|
|
|
if ms.luaModule, err = lua.NewModule(mi.args, ms.luaState, socket); err != nil {
|
|
return nil, errors.New("error with creating new module: " + err.Error())
|
|
}
|
|
|
|
// TODO: here need to register API for communication to logging subsystem
|
|
|
|
luar.Register(ms.luaState.L, "__config", luar.Map{
|
|
"get_config_schema": mc.GetConfigSchema,
|
|
"get_default_config": mc.GetDefaultConfig,
|
|
"get_current_config": mc.GetCurrentConfig,
|
|
"get_event_data_schema": mc.GetEventDataSchema,
|
|
"get_event_config_schema": mc.GetEventConfigSchema,
|
|
"get_default_event_config": mc.GetDefaultEventConfig,
|
|
"get_current_event_config": mc.GetCurrentEventConfig,
|
|
"set_current_config": func(c string) bool {
|
|
if mc.SetCurrentConfig(c) {
|
|
ms.wg.Add(1)
|
|
go func() {
|
|
defer ms.wg.Done()
|
|
ms.luaModule.ControlMsg("update_config", c)
|
|
}()
|
|
return true
|
|
}
|
|
return false
|
|
},
|
|
"get_module_info": func() string {
|
|
if dinfo, err := json.Marshal(mc); err == nil {
|
|
return string(dinfo)
|
|
}
|
|
return ""
|
|
},
|
|
"ctx": luar.Map{
|
|
"agent_id": mc.AgentID,
|
|
"os": mc.OS,
|
|
"name": mc.Name,
|
|
"version": mc.Version,
|
|
"events": mc.Events,
|
|
"last_update": mc.LastUpdate,
|
|
},
|
|
})
|
|
|
|
ms.status = agent.ModuleStatus_LOADED
|
|
return ms, nil
|
|
}
|
|
|
|
// Start is function for running server module
|
|
func (ms *ModuleState) Start() error {
|
|
switch ms.status {
|
|
case agent.ModuleStatus_UNKNOWN:
|
|
return errors.New("module " + ms.name + " can't loaded")
|
|
case agent.ModuleStatus_RUNNING:
|
|
return errors.New("module " + ms.name + " already running")
|
|
case agent.ModuleStatus_FREED:
|
|
return errors.New("module " + ms.name + " already closed")
|
|
case agent.ModuleStatus_LOADED:
|
|
fallthrough
|
|
case agent.ModuleStatus_STOPPED:
|
|
if !ms.cbStart() {
|
|
return errors.New("module socket for " + ms.name + " not registered")
|
|
}
|
|
ms.wg.Add(1)
|
|
ms.status = agent.ModuleStatus_RUNNING
|
|
go func(ms *ModuleState) {
|
|
defer ms.wg.Done()
|
|
ms.luaModule.Start()
|
|
ms.status = agent.ModuleStatus_STOPPED
|
|
}(ms)
|
|
default:
|
|
return errors.New("undefined module " + ms.name + " status")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Stop is function for stopping server module
|
|
func (ms *ModuleState) Stop() error {
|
|
switch ms.status {
|
|
case agent.ModuleStatus_UNKNOWN:
|
|
return errors.New("module " + ms.name + " can't loaded")
|
|
case agent.ModuleStatus_LOADED:
|
|
ms.status = agent.ModuleStatus_STOPPED
|
|
case agent.ModuleStatus_STOPPED:
|
|
return errors.New("module " + ms.name + " already stopped")
|
|
case agent.ModuleStatus_FREED:
|
|
return errors.New("module " + ms.name + " already closed")
|
|
case agent.ModuleStatus_RUNNING:
|
|
ms.luaModule.Stop()
|
|
if !ms.cbStop() {
|
|
return errors.New("can't stop module socket for " + ms.name)
|
|
}
|
|
ms.status = agent.ModuleStatus_STOPPED
|
|
default:
|
|
return errors.New("undefined module " + ms.name + " status")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Close is function for release module object
|
|
func (ms *ModuleState) Close() error {
|
|
switch ms.status {
|
|
case agent.ModuleStatus_UNKNOWN:
|
|
return errors.New("module " + ms.name + " can't loaded")
|
|
case agent.ModuleStatus_LOADED:
|
|
return errors.New("module " + ms.name + " wasn't running")
|
|
case agent.ModuleStatus_FREED:
|
|
return errors.New("module " + ms.name + " already closed")
|
|
case agent.ModuleStatus_RUNNING:
|
|
ms.luaModule.Stop()
|
|
if !ms.cbStop() {
|
|
return errors.New("can't stop module socket for " + ms.name)
|
|
}
|
|
ms.status = agent.ModuleStatus_STOPPED
|
|
fallthrough
|
|
case agent.ModuleStatus_STOPPED:
|
|
ms.wg.Wait()
|
|
luar.Register(ms.luaState.L, "__config", luar.Map{})
|
|
ms.luaModule.Close()
|
|
ms.luaState = nil
|
|
ms.status = agent.ModuleStatus_FREED
|
|
default:
|
|
return errors.New("undefined module " + ms.name + " status")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetName is function that return module name
|
|
func (ms *ModuleState) GetName() string {
|
|
return ms.name
|
|
}
|
|
|
|
// GetStatus is function that return module status
|
|
func (ms *ModuleState) GetStatus() agent.ModuleStatus_Status {
|
|
return ms.status
|
|
}
|
|
|
|
// GetResult is function that return module re3sult after close
|
|
func (ms *ModuleState) GetResult() string {
|
|
return ms.luaModule.GetResult()
|
|
}
|
|
|
|
// GetState is function that return current lua state
|
|
func (ms *ModuleState) GetState() *lua.State {
|
|
return ms.luaState
|
|
}
|
|
|
|
// GetModule is function that return current lua module object
|
|
func (ms *ModuleState) GetModule() *lua.Module {
|
|
return ms.luaModule
|
|
}
|
|
|
|
// GetItem is function that return module item (args, files and config)
|
|
func (ms *ModuleState) GetItem() *ModuleItem {
|
|
return ms.item
|
|
}
|