Skip to content

Commit f6d4bb2

Browse files
committed
save progress
1 parent a08060b commit f6d4bb2

File tree

17 files changed

+1936
-1000
lines changed

17 files changed

+1936
-1000
lines changed

openrpc.json

Lines changed: 0 additions & 809 deletions
This file was deleted.

pkg/api/perf.go

Lines changed: 246 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,255 @@ package api
22

33
import (
44
"context"
5+
"fmt"
56

6-
"github.com/threefoldtech/zos/pkg"
7+
"github.com/rs/zerolog/log"
8+
"github.com/threefoldtech/zos/pkg/perf/cpubench"
9+
"github.com/threefoldtech/zos/pkg/perf/iperf"
710
)
811

9-
func (g *Api) PerfGetHandler(ctx context.Context, taskName string) (pkg.TaskResult, error) {
10-
return g.performanceMonitorStub.Get(ctx, taskName)
12+
type CpuBenchTaskResult struct {
13+
Name string `json:"name"`
14+
Description string `json:"description"`
15+
Timestamp uint64 `json:"timestamp"`
16+
Result cpubench.CPUBenchmarkResult `json:"result"`
1117
}
1218

13-
func (g *Api) PerfGetAllHandler(ctx context.Context) ([]pkg.TaskResult, error) {
14-
return g.performanceMonitorStub.GetAll(ctx)
19+
func (g *Api) PerfGetCpuBench(ctx context.Context) (CpuBenchTaskResult, error) {
20+
res, err := g.performanceMonitorStub.Get(ctx, "cpu-benchmark")
21+
if err != nil {
22+
return CpuBenchTaskResult{}, err
23+
}
24+
25+
innerResult, ok := res.Result.(cpubench.CPUBenchmarkResult)
26+
if !ok {
27+
return CpuBenchTaskResult{}, err
28+
}
29+
30+
return CpuBenchTaskResult{
31+
Name: res.Name,
32+
Description: res.Description,
33+
Timestamp: res.Timestamp,
34+
Result: innerResult,
35+
}, nil
36+
}
37+
38+
type AllTaskResult struct {
39+
CpuBenchmark CpuBenchTaskResult `json:"cpu_benchmark"`
40+
HealthCheck HealthTaskResult `json:"health_check"`
41+
Iperf IperfTaskResult `json:"iperf"`
42+
PublicIp PublicIpTaskResult `json:"public_ip"`
43+
}
44+
45+
func (g *Api) PerfGetAllHandler(ctx context.Context) (AllTaskResult, error) {
46+
res, err := g.performanceMonitorStub.GetAll(ctx)
47+
if err != nil {
48+
return AllTaskResult{}, nil
49+
}
50+
51+
results := AllTaskResult{}
52+
for _, result := range res {
53+
switch result.Name {
54+
case "cpu-benchmark":
55+
innerResult, ok := result.Result.(cpubench.CPUBenchmarkResult)
56+
if !ok {
57+
return AllTaskResult{}, err
58+
}
59+
60+
results.CpuBenchmark = CpuBenchTaskResult{
61+
Name: result.Name,
62+
Description: result.Description,
63+
Timestamp: result.Timestamp,
64+
Result: innerResult,
65+
}
66+
case "healthcheck":
67+
innerResult, ok := result.Result.(map[string][]string)
68+
if !ok {
69+
return AllTaskResult{}, err
70+
}
71+
72+
healthResult := HealthTaskResult{
73+
Name: result.Name,
74+
Description: result.Description,
75+
Timestamp: result.Timestamp,
76+
}
77+
78+
for key, val := range innerResult {
79+
healthResult.Result = append(healthResult.Result, HealthReport{
80+
TestName: key,
81+
Errors: val,
82+
})
83+
}
84+
85+
results.HealthCheck = healthResult
86+
case "iperf":
87+
innerResult, ok := result.Result.(iperf.IperfResult)
88+
if !ok {
89+
return AllTaskResult{}, err
90+
}
91+
92+
results.Iperf = IperfTaskResult{
93+
Name: result.Name,
94+
Description: result.Description,
95+
Timestamp: result.Timestamp,
96+
Result: innerResult,
97+
}
98+
case "public-ip-validation":
99+
// innerResult, ok := result.Result.(map[string]publicip.IPReport)
100+
// if !ok {
101+
// return AllTaskResult{}, err
102+
// }
103+
104+
// ipResults := PublicIpTaskResult{
105+
// Name: result.Name,
106+
// Description: result.Description,
107+
// Timestamp: result.Timestamp,
108+
// }
109+
110+
// for key, report := range innerResult {
111+
// report.Ip = key
112+
// ipResults.Result = append(ipResults.Result, report)
113+
// }
114+
// results.PublicIp = ipResults
115+
}
116+
}
117+
118+
return results, nil
119+
}
120+
121+
// ==========================================================
122+
type HealthReport struct {
123+
TestName string `json:"test_name"`
124+
Errors []string `json:"errors"`
125+
}
126+
127+
type HealthTaskResult struct {
128+
Name string `json:"name"`
129+
Description string `json:"description"`
130+
Timestamp uint64 `json:"timestamp"`
131+
Result []HealthReport `json:"result"`
132+
}
133+
134+
func (g *Api) PerfGetHealth(ctx context.Context) (HealthTaskResult, error) {
135+
taskResult, err := g.performanceMonitorStub.Get(ctx, "healthcheck")
136+
if err != nil {
137+
return HealthTaskResult{}, err
138+
}
139+
140+
healthTaskResult := HealthTaskResult{
141+
Name: taskResult.Name,
142+
Description: taskResult.Description,
143+
Timestamp: taskResult.Timestamp,
144+
}
145+
146+
// convert inner result from map[string][]string to []HealthReport
147+
innerResult, ok := taskResult.Result.(map[string]interface{})
148+
if !ok {
149+
return HealthTaskResult{}, fmt.Errorf("failed to assert type: %w", err)
150+
}
151+
152+
for testName, errors := range innerResult {
153+
errorStrings := []string{}
154+
errorList, ok := errors.([]interface{})
155+
if !ok {
156+
return HealthTaskResult{}, fmt.Errorf("failed to assert type: %w", err)
157+
}
158+
159+
for _, errorItem := range errorList {
160+
errorString, ok := errorItem.(string)
161+
if !ok {
162+
return HealthTaskResult{}, fmt.Errorf("failed to assert type: %w", err)
163+
}
164+
errorStrings = append(errorStrings, errorString)
165+
}
166+
167+
healthReport := HealthReport{
168+
TestName: testName,
169+
Errors: errorStrings,
170+
}
171+
172+
healthTaskResult.Result = append(healthTaskResult.Result, healthReport)
173+
}
174+
175+
return healthTaskResult, nil
176+
}
177+
178+
type Report struct {
179+
Ip string `json:"ip"`
180+
State string `json:"state"`
181+
Reason string `json:"reason"`
182+
}
183+
184+
type PublicIpTaskResult struct {
185+
Name string `json:"name"`
186+
Description string `json:"description"`
187+
Timestamp uint64 `json:"timestamp"`
188+
Result []Report `json:"result"`
189+
}
190+
191+
func (g *Api) PerfGetPublicIP(ctx context.Context) (PublicIpTaskResult, error) {
192+
taskResult, err := g.performanceMonitorStub.Get(ctx, "public-ip-validation")
193+
if err != nil {
194+
return PublicIpTaskResult{}, err
195+
}
196+
197+
response := PublicIpTaskResult{
198+
Name: taskResult.Name,
199+
Description: taskResult.Description,
200+
Timestamp: taskResult.Timestamp,
201+
}
202+
203+
// convert inner result from map[string]IpReport into []IpReport
204+
innerResult, ok := taskResult.Result.(map[string]interface{})
205+
if !ok {
206+
return PublicIpTaskResult{}, fmt.Errorf("failed to assert type: %w", err)
207+
}
208+
209+
reports := []Report{}
210+
for ip, report := range innerResult {
211+
212+
r, ok := report.(map[string]interface{})
213+
if !ok {
214+
return PublicIpTaskResult{}, fmt.Errorf("failed to assert report type: %w", err)
215+
}
216+
217+
rep := Report{
218+
Ip: ip,
219+
State: r["state"].(string),
220+
Reason: r["reason"].(string),
221+
}
222+
223+
reports = append(reports, rep)
224+
}
225+
226+
response.Result = reports
227+
return response, nil
228+
}
229+
230+
type IperfTaskResult struct {
231+
Name string `json:"name"`
232+
Description string `json:"description"`
233+
Timestamp uint64 `json:"timestamp"`
234+
Result iperf.IperfResult `json:"result"`
235+
}
236+
237+
func (g *Api) PerfGetIperf(ctx context.Context) (IperfTaskResult, error) {
238+
res, err := g.performanceMonitorStub.GetIperfTaskResult(ctx, "iperf")
239+
if err != nil {
240+
return IperfTaskResult{}, err
241+
}
242+
243+
innerResult, ok := res.Result.(iperf.IperfResult)
244+
if !ok {
245+
return IperfTaskResult{}, err
246+
}
247+
log.Info().Msgf("inner %v", innerResult)
248+
log.Info().Msgf("inner type %T", innerResult)
249+
250+
return IperfTaskResult{
251+
Name: res.Name,
252+
Description: res.Description,
253+
Timestamp: res.Timestamp,
254+
Result: innerResult,
255+
}, nil
15256
}

pkg/api/readme.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
11
# Zos Internal API
22

33
This package contains all the Zos methods. By default, it isn't exposed but should be extended through any server. The main idea is that it exclusively takes and returns Zos types, allowing each API server to map these types to the types used in its protocol.
4+
5+
6+
This is intermidate api that wrap all the api types in a good way, to not have maps or interface{}, this should be extened in other server.
7+
8+
9+
all response/param types here should be a valid json types (numeric, string, bool, object, null) so no any and no map.

pkg/api/system.go

Lines changed: 80 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"os/exec"
66
"strings"
77

8-
"github.com/threefoldtech/zos/pkg/capacity/dmi"
98
"github.com/threefoldtech/zos/pkg/diagnostics"
109
)
1110

@@ -30,10 +29,54 @@ func (g *Api) SystemVersionHandler(ctx context.Context) Version {
3029

3130
return version
3231
}
33-
34-
func (g *Api) SystemDMIHandler() (dmi.DMI, error) {
32+
func (g *Api) SystemDMIHandler() (DMI, error) {
3533
dmi, err := g.oracle.DMI()
36-
return *dmi, err
34+
if err != nil {
35+
return DMI{}, err
36+
}
37+
38+
ret := DMI{
39+
Tooling: Tooling{
40+
Aggregator: dmi.Tooling.Aggregator,
41+
Decoder: dmi.Tooling.Decoder,
42+
},
43+
Sections: func() []Section {
44+
var sections []Section
45+
for _, sec := range dmi.Sections {
46+
section := Section{
47+
HandleLine: sec.HandleLine,
48+
TypeStr: sec.TypeStr,
49+
Type: int(sec.Type),
50+
SubSections: func() []SubSection {
51+
var subsections []SubSection
52+
for _, subsec := range sec.SubSections {
53+
subsection := SubSection{
54+
Title: subsec.Title,
55+
Properties: func() []PropertyData {
56+
var properties []PropertyData
57+
for key, prop := range subsec.Properties {
58+
property := PropertyData{
59+
Name: key,
60+
Val: prop.Val,
61+
Items: prop.Items,
62+
}
63+
properties = append(properties, property)
64+
}
65+
return properties
66+
}(),
67+
}
68+
subsections = append(subsections, subsection)
69+
}
70+
return subsections
71+
}(),
72+
}
73+
sections = append(sections, section)
74+
}
75+
return sections
76+
}(),
77+
}
78+
79+
return ret, nil
3780
}
3881

3982
func (g *Api) SystemHypervisorHandler() (string, error) {
@@ -43,3 +86,36 @@ func (g *Api) SystemHypervisorHandler() (string, error) {
4386
func (g *Api) SystemDiagnosticsHandler(ctx context.Context) (diagnostics.Diagnostics, error) {
4487
return g.diagnosticsManager.GetSystemDiagnostics(ctx)
4588
}
89+
90+
// PropertyData represents a key value pair with optional list of items
91+
type PropertyData struct {
92+
Name string `json:"name,omitempty"`
93+
Val string `json:"value"`
94+
Items []string `json:"items,omitempty"`
95+
}
96+
97+
// Section represents a complete section like BIOS or Baseboard
98+
type Section struct {
99+
HandleLine string `json:"handleline"`
100+
TypeStr string `json:"typestr,omitempty"`
101+
Type int `json:"typenum"`
102+
SubSections []SubSection `json:"subsections"`
103+
}
104+
105+
// SubSection represents part of a section, identified by a title
106+
type SubSection struct {
107+
Title string `json:"title"`
108+
Properties []PropertyData `json:"properties,omitempty"`
109+
}
110+
111+
type DMI struct {
112+
Tooling Tooling `json:"tooling"`
113+
Sections []Section `json:"sections"`
114+
}
115+
116+
// Tooling holds the information and version about the tool used to
117+
// read DMI information
118+
type Tooling struct {
119+
Aggregator string `json:"aggregator"`
120+
Decoder string `json:"decoder"`
121+
}

pkg/apirpc/converter.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package apirpc
2+
3+
import "encoding/json"
4+
5+
// This function heavily used and it depends on matching json tags on both types
6+
func convert(input any, output any) error {
7+
data, err := json.Marshal(input)
8+
if err != nil {
9+
return err
10+
}
11+
12+
if err := json.Unmarshal(data, &output); err != nil {
13+
return err
14+
}
15+
16+
return nil
17+
}

0 commit comments

Comments
 (0)