Skip to content

Commit a450ec6

Browse files
committed
mycelium messaging integration
- generated openrpc file with all methods/types for api - new `api` pkg handling both modes normal/light handlers with defined param/return type, decoupled from the messaging part - new `reciever` pkg handling the messaging over mycelium binary with handlers mapped to api pkg - update monitor pkg/stub for better defined-typed results
1 parent 1d8f2ec commit a450ec6

19 files changed

+2328
-34
lines changed

mycelium-openrpc.json

Lines changed: 1093 additions & 0 deletions
Large diffs are not rendered by default.

pkg/api/api.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package api
2+
3+
import (
4+
"errors"
5+
"time"
6+
7+
"github.com/patrickmn/go-cache"
8+
"github.com/threefoldtech/zbus"
9+
"github.com/threefoldtech/zosbase/pkg/capacity"
10+
"github.com/threefoldtech/zosbase/pkg/diagnostics"
11+
"github.com/threefoldtech/zosbase/pkg/stubs"
12+
)
13+
14+
const (
15+
cacheDefaultExpiration = 24 * time.Hour
16+
cacheDefaultCleanup = 24 * time.Hour
17+
lightMode = "light"
18+
)
19+
20+
var (
21+
ErrNotSupportedInLightMode = errors.New("method is not supported in light mode")
22+
)
23+
24+
type API struct {
25+
mode string
26+
oracle *capacity.ResourceOracle
27+
versionMonitorStub *stubs.VersionMonitorStub
28+
systemMonitorStub *stubs.SystemMonitorStub
29+
provisionStub *stubs.ProvisionStub
30+
networkerStub *stubs.NetworkerStub
31+
networkerLightStub *stubs.NetworkerLightStub
32+
statisticsStub *stubs.StatisticsStub
33+
storageStub *stubs.StorageModuleStub
34+
performanceMonitorStub *stubs.PerformanceMonitorStub
35+
diagnosticsManager *diagnostics.DiagnosticsManager
36+
inMemCache *cache.Cache
37+
}
38+
39+
func NewAPI(client zbus.Client, msgBrokerCon string, mode string) (*API, error) {
40+
diagnosticsManager, err := diagnostics.NewDiagnosticsManager(msgBrokerCon, client)
41+
if err != nil {
42+
return nil, err
43+
}
44+
45+
storageModuleStub := stubs.NewStorageModuleStub(client)
46+
47+
api := &API{
48+
mode: mode,
49+
storageStub: storageModuleStub,
50+
diagnosticsManager: diagnosticsManager,
51+
oracle: capacity.NewResourceOracle(storageModuleStub),
52+
versionMonitorStub: stubs.NewVersionMonitorStub(client),
53+
systemMonitorStub: stubs.NewSystemMonitorStub(client),
54+
provisionStub: stubs.NewProvisionStub(client),
55+
statisticsStub: stubs.NewStatisticsStub(client),
56+
performanceMonitorStub: stubs.NewPerformanceMonitorStub(client),
57+
}
58+
59+
if mode == lightMode {
60+
api.networkerLightStub = stubs.NewNetworkerLightStub(client)
61+
} else {
62+
api.networkerStub = stubs.NewNetworkerStub(client)
63+
}
64+
65+
api.inMemCache = cache.New(cacheDefaultExpiration, cacheDefaultCleanup)
66+
return api, nil
67+
}
68+
69+
func (a *API) isLightMode() bool {
70+
return a.mode == lightMode
71+
}

pkg/api/deployment.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package api
2+
3+
import (
4+
"context"
5+
"errors"
6+
7+
"github.com/threefoldtech/zosbase/pkg/gridtypes"
8+
)
9+
10+
func (a *API) DeploymentDeployHandler(ctx context.Context, deployment gridtypes.Deployment) error {
11+
twinID, ok := ctx.Value("twin_id").(uint32)
12+
if !ok {
13+
return errors.New("could not get twin_id from context")
14+
}
15+
return a.provisionStub.CreateOrUpdate(ctx, twinID, deployment, false)
16+
}
17+
18+
func (a *API) DeploymentUpdateHandler(ctx context.Context, deployment gridtypes.Deployment) error {
19+
twinID, ok := ctx.Value("twin_id").(uint32)
20+
if !ok {
21+
return errors.New("could not get twin_id from context")
22+
}
23+
return a.provisionStub.CreateOrUpdate(ctx, twinID, deployment, true)
24+
}
25+
26+
func (a *API) DeploymentDeleteHandler(ctx context.Context, contractID uint64) error {
27+
return errors.New("deletion over the api is disabled, please cancel your contract instead")
28+
}
29+
30+
func (a *API) DeploymentGetHandler(ctx context.Context, contractID uint64) (gridtypes.Deployment, error) {
31+
twinID, ok := ctx.Value("twin_id").(uint32)
32+
if !ok {
33+
return gridtypes.Deployment{}, errors.New("could not get twin_id from context")
34+
}
35+
return a.provisionStub.Get(ctx, twinID, contractID)
36+
}
37+
38+
func (a *API) DeploymentListHandler(ctx context.Context) ([]gridtypes.Deployment, error) {
39+
twinID, ok := ctx.Value("twin_id").(uint32)
40+
if !ok {
41+
return nil, errors.New("could not get twin_id from context")
42+
}
43+
return a.provisionStub.List(ctx, twinID)
44+
}
45+
46+
func (a *API) DeploymentChangesHandler(ctx context.Context, contractID uint64) ([]gridtypes.Workload, error) {
47+
twinID, ok := ctx.Value("twin_id").(uint32)
48+
if !ok {
49+
return nil, errors.New("could not get twin_id from context")
50+
}
51+
return a.provisionStub.Changes(ctx, twinID, contractID)
52+
}

pkg/api/location.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package api
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/patrickmn/go-cache"
8+
"github.com/threefoldtech/zosbase/pkg/geoip"
9+
)
10+
11+
const (
12+
locationCacheKey = "location"
13+
)
14+
15+
func (a *API) LocationGet(ctx context.Context) (geoip.Location, error) {
16+
if loc, found := a.inMemCache.Get(locationCacheKey); found {
17+
if loc, ok := loc.(geoip.Location); ok {
18+
return loc, nil
19+
}
20+
21+
return geoip.Location{}, fmt.Errorf("failed to convert cached location")
22+
}
23+
24+
loc, err := geoip.Fetch()
25+
if err != nil {
26+
return geoip.Location{}, err
27+
}
28+
a.inMemCache.Set(locationCacheKey, loc, cache.DefaultExpiration)
29+
30+
return loc, nil
31+
}

pkg/api/logs.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package api
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"os"
7+
"path/filepath"
8+
)
9+
10+
// GetVmLogsHandler returns VM logs
11+
func (a *API) GetVmLogsHandler(ctx context.Context, fileName string) (string, error) {
12+
rootPath := "/var/cache/modules/vmd/logs/"
13+
fullPath := filepath.Join(rootPath, fileName)
14+
content, err := os.ReadFile(fullPath)
15+
if err != nil {
16+
return "", fmt.Errorf("failed to read file, path: %s, %w", fullPath, err)
17+
}
18+
19+
return string(content), nil
20+
}

pkg/api/monitor.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package api
2+
3+
import (
4+
"context"
5+
6+
"github.com/threefoldtech/zosbase/pkg"
7+
)
8+
9+
func (a *API) PerfSpeed(ctx context.Context) (pkg.IperfTaskResult, error) {
10+
return a.performanceMonitorStub.GetIperfTaskResult(ctx)
11+
}
12+
13+
func (a *API) PerfHealth(ctx context.Context) (pkg.HealthTaskResult, error) {
14+
return a.performanceMonitorStub.GetHealthTaskResult(ctx)
15+
}
16+
17+
func (a *API) PerfPublicIp(ctx context.Context) (pkg.PublicIpTaskResult, error) {
18+
return a.performanceMonitorStub.GetPublicIpTaskResult(ctx)
19+
}
20+
21+
func (a *API) PerfBenchmark(ctx context.Context) (pkg.CpuBenchTaskResult, error) {
22+
return a.performanceMonitorStub.GetCpuBenchTaskResult(ctx)
23+
}
24+
25+
func (a *API) PerfAll(ctx context.Context) (pkg.AllTaskResult, error) {
26+
return a.performanceMonitorStub.GetAllTaskResult(ctx)
27+
}

pkg/api/network.go

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
package api
2+
3+
import (
4+
"context"
5+
"errors"
6+
"fmt"
7+
"net"
8+
9+
"github.com/threefoldtech/zosbase/pkg"
10+
"github.com/threefoldtech/zosbase/pkg/gridtypes"
11+
)
12+
13+
func (a *API) NetworkWGPorts(ctx context.Context) ([]uint, error) {
14+
if a.isLightMode() {
15+
return nil, ErrNotSupportedInLightMode
16+
}
17+
return a.networkerStub.WireguardPorts(ctx)
18+
}
19+
20+
func (a *API) NetworkPublicConfigGet(ctx context.Context, _ any) (pkg.PublicConfig, error) {
21+
if a.isLightMode() {
22+
return pkg.PublicConfig{}, ErrNotSupportedInLightMode
23+
}
24+
25+
return a.networkerStub.GetPublicConfig(ctx)
26+
}
27+
28+
func (a *API) NetworkHasIPv6(ctx context.Context) (bool, error) {
29+
if a.isLightMode() {
30+
return false, nil
31+
}
32+
33+
ipData, err := a.networkerStub.GetPublicIPv6Subnet(ctx)
34+
hasIP := ipData.IP != nil && err == nil
35+
return hasIP, nil
36+
37+
}
38+
39+
func (a *API) NetworkListPublicIPs(ctx context.Context) ([]string, error) {
40+
if a.isLightMode() {
41+
return nil, ErrNotSupportedInLightMode
42+
}
43+
44+
return a.provisionStub.ListPublicIPs(ctx)
45+
}
46+
47+
func (a *API) NetworkListPrivateIPs(ctx context.Context, networkName string) ([]string, error) {
48+
name := gridtypes.Name(networkName)
49+
twinID, ok := ctx.Value("twin_id").(uint32)
50+
if !ok {
51+
return nil, errors.New("could not get twin_id from context")
52+
}
53+
return a.provisionStub.ListPrivateIPs(ctx, twinID, name)
54+
}
55+
56+
func (a *API) NetworkInterfaces(ctx context.Context) (pkg.Interfaces, error) {
57+
if a.isLightMode() {
58+
return a.networkerLightStub.Interfaces(ctx, "zos", "")
59+
}
60+
61+
type q struct {
62+
inf string
63+
ns string
64+
rename string
65+
}
66+
result := pkg.Interfaces{
67+
Interfaces: make(map[string]pkg.Interface),
68+
}
69+
for _, i := range []q{{"zos", "", "zos"}, {"nygg6", "ndmz", "ygg"}} {
70+
ips, mac, err := a.networkerStub.Addrs(ctx, i.inf, i.ns)
71+
if err != nil {
72+
return pkg.Interfaces{Interfaces: make(map[string]pkg.Interface)}, fmt.Errorf("failed to get ips for '%s' interface: %w", i.inf, err)
73+
}
74+
75+
iface := pkg.Interface{
76+
Name: i.rename,
77+
Mac: mac,
78+
IPs: []net.IPNet{},
79+
}
80+
81+
for _, item := range ips {
82+
ipNet := net.IPNet{
83+
IP: item,
84+
Mask: nil,
85+
}
86+
iface.IPs = append(iface.IPs, ipNet)
87+
}
88+
89+
result.Interfaces[i.rename] = iface
90+
}
91+
92+
return result, nil
93+
}
94+
95+
// all interfaces on the node
96+
func (a *API) AdminInterfaces(ctx context.Context) (pkg.Interfaces, error) {
97+
if a.isLightMode() {
98+
return a.networkerLightStub.Interfaces(ctx, "", "")
99+
}
100+
101+
return a.networkerStub.Interfaces(ctx, "", "")
102+
}
103+
104+
func (a *API) AdminSetPublicNIC(ctx context.Context, device string) error {
105+
if a.isLightMode() {
106+
return ErrNotSupportedInLightMode
107+
}
108+
return a.networkerStub.SetPublicExitDevice(ctx, device)
109+
}
110+
111+
func (a *API) AdminGetPublicNIC(ctx context.Context) (pkg.ExitDevice, error) {
112+
if a.isLightMode() {
113+
return pkg.ExitDevice{}, ErrNotSupportedInLightMode
114+
}
115+
116+
return a.networkerStub.GetPublicExitDevice(ctx)
117+
}

pkg/api/statistics.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package api
2+
3+
import (
4+
"context"
5+
6+
"github.com/threefoldtech/zosbase/pkg"
7+
)
8+
9+
func (a *API) Statistics(ctx context.Context) (pkg.Counters, error) {
10+
return a.statisticsStub.GetCounters(ctx)
11+
}
12+
13+
func (a *API) GpuList(ctx context.Context) ([]pkg.GPUInfo, error) {
14+
return a.statisticsStub.ListGPUs(ctx)
15+
}

pkg/api/storage.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package api
2+
3+
import (
4+
"context"
5+
6+
"github.com/threefoldtech/zosbase/pkg"
7+
)
8+
9+
func (a *API) StoragePoolsHandler(ctx context.Context) ([]pkg.PoolMetrics, error) {
10+
return a.storageStub.Metrics(ctx)
11+
}

pkg/api/system.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package api
2+
3+
import (
4+
"context"
5+
"os/exec"
6+
"strings"
7+
8+
"github.com/threefoldtech/zosbase/pkg"
9+
"github.com/threefoldtech/zosbase/pkg/capacity/dmi"
10+
"github.com/threefoldtech/zosbase/pkg/diagnostics"
11+
)
12+
13+
func (a *API) SystemVersion(ctx context.Context) (Version, error) {
14+
output, err := exec.CommandContext(ctx, "zinit", "-V").CombinedOutput()
15+
var zInitVer string
16+
if err != nil {
17+
zInitVer = err.Error()
18+
} else {
19+
zInitVer = strings.TrimSpace(strings.TrimPrefix(string(output), "zinit"))
20+
}
21+
22+
version := Version{
23+
Zos: a.versionMonitorStub.GetVersion(ctx).String(),
24+
Zinit: zInitVer,
25+
}
26+
27+
return version, nil
28+
}
29+
30+
func (a *API) SystemDMI(ctx context.Context) (dmi.DMI, error) {
31+
dmi, err := a.oracle.DMI()
32+
return *dmi, err
33+
}
34+
35+
func (a *API) SystemHypervisor(ctx context.Context) (string, error) {
36+
return a.oracle.GetHypervisor()
37+
}
38+
39+
func (a *API) SystemDiagnostics(ctx context.Context) (diagnostics.Diagnostics, error) {
40+
return a.diagnosticsManager.GetSystemDiagnostics(ctx)
41+
}
42+
43+
func (a *API) SystemNodeFeatures(ctx context.Context) []pkg.NodeFeature {
44+
return a.systemMonitorStub.GetNodeFeatures(ctx)
45+
}

0 commit comments

Comments
 (0)