mirror of
https://github.com/ultravioletrs/cocos.git
synced 2026-08-07 07:14:50 +00:00
55afe4c038
* Optimize QEMU launch and add V-sock support Refactored QEMU argument construction and launching logic by removing the dependency on 'agent.Computation'. This simplification makes the VM creation process more streamlined. Additionally, introduced V-sock capabilities in the QEMU configuration to facilitate improved guest-host communication. Updated the README to include kernel module setup instructions for the new V-sock feature. The V-sock implementation enables VMs to use a consistent communication channel that is not affected by network configuration changes, enhancing reliability and potential interoperability with host services. It's important to ensure that the necessary kernel modules are loaded as part of the setup process, as documented. Signed-off-by: SammyOina <sammyoina@gmail.com> * Add vsock-based communication to manager Introduced virtual socket (vsock) communication abilities in the manager package by implementing a new socket service. This includes establishing a vsock listener and stub methods for sending computation results and cleaning up resources. The addition provides the groundwork for interprocess communication between guest and host in virtualized environments. - Integrated the `mdlayher/vsock` library for handling virtual socket operations. - Created a new `sockService` struct to encapsulate vsock listener handling. - Implemented `NewVsock` constructor to initialize the listener with domain value `3`. - Added placeholder methods for future computation sending and service closing logic. This enhancement targets scenarios where efficient VM-to-host communication is required. Signed-off-by: SammyOina <sammyoina@gmail.com> * remove env Signed-off-by: SammyOina <sammyoina@gmail.com> * Refactor agent config and use vsock Introduce `AgentConfig` struct to group agent-related configurations, and update `Computation` struct to include the new `AgentConfig` field. Replace command-line computation extraction with vsock-based config retrieval for robustness and decoupling. The agent configuration is now read from a vsock connection during runtime, allowing for more dynamic and flexible deployments. Adjusted the main agent application logic to support these configuration changes, and corresponding changes have been made in the manager to facilitate vsock communication. This approach aligns with modern practices for microservices by streamlining configuration management and reducing reliance on static command-line parameters. Moreover, it enhances the scalability of the agent service by allowing configuration to be managed externally. Signed-off-by: SammyOina <sammyoina@gmail.com> * Refactor agent config and remove deprecated code Consolidated agent configuration management into a single `AgentConfig` message and pruned deprecated Protobuf `ComputationReq`, `DatasetReq`, and `AlgorithmReq` messages. Adapted corresponding manager service logic to the new configuration structure. These modifications align with updated manager API schema, facilitate clearer configuration handling, and improve maintainability. Signed-off-by: SammyOina <sammyoina@gmail.com> * send configuration Signed-off-by: SammyOina <sammyoina@gmail.com> * Switch agent to listen mode for manager connections Previously, the agent established a connection to the manager using a direct dial. This change shifts the setup to where the agent listens on a specified port and accepts incoming connections. It ensures that the agent properly handles incoming requests by initiating a listening socket and waiting for the manager to connect, enhancing the system's flexibility in connection management. This adjustment also includes graceful closure of the listening socket. Signed-off-by: SammyOina <sammyoina@gmail.com> --------- Signed-off-by: SammyOina <sammyoina@gmail.com>
128 lines
3.8 KiB
Go
128 lines
3.8 KiB
Go
// Copyright (c) Ultraviolet
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
package manager
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net"
|
|
"strconv"
|
|
|
|
mglog "github.com/absmach/magistrala/logger"
|
|
"github.com/absmach/magistrala/pkg/errors"
|
|
"github.com/ultravioletrs/cocos/agent"
|
|
"github.com/ultravioletrs/cocos/internal/events"
|
|
"github.com/ultravioletrs/cocos/manager/qemu"
|
|
)
|
|
|
|
var (
|
|
// ErrMalformedEntity indicates malformed entity specification (e.g.
|
|
// invalid username or password).
|
|
ErrMalformedEntity = errors.New("malformed entity specification")
|
|
|
|
// ErrUnauthorizedAccess indicates missing or invalid credentials provided
|
|
// when accessing a protected resource.
|
|
ErrUnauthorizedAccess = errors.New("missing or invalid credentials provided")
|
|
|
|
// ErrNotFound indicates a non-existent entity request.
|
|
ErrNotFound = errors.New("entity not found")
|
|
|
|
// ErrFailedToAllocatePort indicates no free port was found on host.
|
|
ErrFailedToAllocatePort = errors.New("failed to allocate free port on host")
|
|
)
|
|
|
|
// Service specifies an API that must be fulfilled by the domain service
|
|
// implementation, and all of its decorators (e.g. logging & metrics).
|
|
type Service interface {
|
|
Run(ctx context.Context, c *Computation) (string, error)
|
|
}
|
|
|
|
type managerService struct {
|
|
qemuCfg qemu.Config
|
|
logger mglog.Logger
|
|
eventSvc events.Service
|
|
hostIP string
|
|
}
|
|
|
|
var _ Service = (*managerService)(nil)
|
|
|
|
// New instantiates the manager service implementation.
|
|
func New(qemuCfg qemu.Config, logger mglog.Logger, eventSvc events.Service, hostIP string) Service {
|
|
return &managerService{
|
|
qemuCfg: qemuCfg,
|
|
eventSvc: eventSvc,
|
|
hostIP: hostIP,
|
|
logger: logger,
|
|
}
|
|
}
|
|
|
|
func (ms *managerService) Run(ctx context.Context, c *Computation) (string, error) {
|
|
ms.publishEvent("vm-provision", c.Id, "starting", json.RawMessage{})
|
|
ac := agent.Computation{
|
|
ID: c.Id,
|
|
Name: c.Name,
|
|
Description: c.Description,
|
|
ResultConsumers: c.ResultConsumers,
|
|
AgentConfig: agent.AgentConfig{
|
|
Port: c.AgentConfig.Port,
|
|
Host: c.AgentConfig.Host,
|
|
KeyFile: c.AgentConfig.KeyFile,
|
|
CertFile: c.AgentConfig.CertFile,
|
|
LogLevel: c.AgentConfig.LogLevel,
|
|
InstanceID: c.AgentConfig.InstanceId,
|
|
NotificationServerURL: c.AgentConfig.NotificationsUrl,
|
|
},
|
|
}
|
|
for _, algo := range c.Algorithms {
|
|
ac.Algorithms = append(ac.Algorithms, agent.Algorithm{ID: algo.Id, Provider: algo.Provider})
|
|
}
|
|
for _, data := range c.Datasets {
|
|
ac.Datasets = append(ac.Datasets, agent.Dataset{ID: data.Id, Provider: data.Provider})
|
|
}
|
|
|
|
agentPort, err := getFreePort()
|
|
if err != nil {
|
|
ms.publishEvent("vm-provision", c.Id, "failed", json.RawMessage{})
|
|
return "", errors.Wrap(ErrFailedToAllocatePort, err)
|
|
}
|
|
ms.qemuCfg.HostFwdAgent = agentPort
|
|
|
|
ms.publishEvent("vm-provision", c.Id, "in-progress", json.RawMessage{})
|
|
if _, err = qemu.CreateVM(ctx, ms.qemuCfg); err != nil {
|
|
ms.publishEvent("vm-provision", c.Id, "failed", json.RawMessage{})
|
|
return "", err
|
|
}
|
|
|
|
if err := SendAgentConfig(uint32(ms.qemuCfg.VSockConfig.GuestCID), ac); err != nil {
|
|
return "", err
|
|
}
|
|
ms.qemuCfg.VSockConfig.GuestCID++
|
|
|
|
ms.publishEvent("vm-provision", c.Id, "complete", json.RawMessage{})
|
|
return fmt.Sprintf("%s:%d", ms.hostIP, ms.qemuCfg.HostFwdAgent), nil
|
|
}
|
|
|
|
func getFreePort() (int, error) {
|
|
listener, err := net.Listen("tcp", "")
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
defer listener.Close()
|
|
_, portStr, err := net.SplitHostPort(listener.Addr().String())
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
port, err := strconv.Atoi(portStr)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return port, nil
|
|
}
|
|
|
|
func (ms *managerService) publishEvent(event, cmpID, status string, details json.RawMessage) {
|
|
if err := ms.eventSvc.SendEvent(event, cmpID, status, details); err != nil {
|
|
ms.logger.Warn(err.Error())
|
|
}
|
|
}
|