Skip to content

Commit e71cf04

Browse files
committed
add admin interface to zos-api
1 parent f169b04 commit e71cf04

File tree

4 files changed

+260
-9
lines changed

4 files changed

+260
-9
lines changed

client/node.go

Lines changed: 76 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ func (n *NodeClient) NetworkListInterfaces(ctx context.Context) (result map[stri
189189

190190
// NetworkListAllInterfaces return all physical devices on a node
191191
func (n *NodeClient) NetworkListAllInterfaces(ctx context.Context) (result map[string]Interface, err error) {
192-
const cmd = "zos.network.admin.interfaces"
192+
const cmd = "zos.admin.interfaces"
193193

194194
err = n.bus.Call(ctx, n.nodeTwin, cmd, nil, &result)
195195

@@ -199,19 +199,92 @@ func (n *NodeClient) NetworkListAllInterfaces(ctx context.Context) (result map[s
199199
// NetworkSetPublicExitDevice select which physical interface to use as an exit device
200200
// setting `iface` to `zos` will then make node run in a single nic setup.
201201
func (n *NodeClient) NetworkSetPublicExitDevice(ctx context.Context, iface string) error {
202-
const cmd = "zos.network.admin.set_public_nic"
202+
const cmd = "zos.admin.set_public_nic"
203203

204204
return n.bus.Call(ctx, n.nodeTwin, cmd, iface, nil)
205205
}
206206

207207
// NetworkGetPublicExitDevice gets the current dual nic setup of the node.
208208
func (n *NodeClient) NetworkGetPublicExitDevice(ctx context.Context) (exit ExitDevice, err error) {
209-
const cmd = "zos.network.admin.get_public_nic"
209+
const cmd = "zos.admin.get_public_nic"
210210

211211
err = n.bus.Call(ctx, n.nodeTwin, cmd, nil, &exit)
212212
return
213213
}
214214

215+
// AdminRebootNode stops all the running services and reboots the node
216+
func (n *NodeClient) AdminRebootNode(ctx context.Context) error {
217+
const cmd = "zos.admin.reboot"
218+
219+
return n.bus.Call(ctx, n.nodeTwin, cmd, nil, nil)
220+
}
221+
222+
// AdminRestartService restarts a zinit service
223+
func (n *NodeClient) AdminRestartService(ctx context.Context, service string) error {
224+
const cmd = "zos.admin.restart"
225+
226+
return n.bus.Call(ctx, n.nodeTwin, cmd, service, nil)
227+
}
228+
229+
// AdminRestartAll restarts all zinit services
230+
func (n *NodeClient) AdminRestartAll(ctx context.Context) error {
231+
const cmd = "zos.admin.restart_all"
232+
233+
return n.bus.Call(ctx, n.nodeTwin, cmd, nil, nil)
234+
}
235+
236+
// AdminShowLogs returns l lines of zinit logs
237+
func (n *NodeClient) AdminShowLogs(ctx context.Context, l int) (logs []byte, err error) {
238+
const cmd = "zos.admin.show_logs"
239+
240+
err = n.bus.Call(ctx, n.nodeTwin, cmd, l, &logs)
241+
return
242+
}
243+
244+
// AdminShowResolve return the content of /etc/resolv.conf
245+
func (n *NodeClient) AdminShowResolve(ctx context.Context) (res []byte, err error) {
246+
const cmd = "zos.admin.show_resolve"
247+
248+
err = n.bus.Call(ctx, n.nodeTwin, cmd, nil, &res)
249+
return
250+
}
251+
252+
// AdminShowOpenConnections return information about all open connections in the node
253+
func (n *NodeClient) AdminShowOpenConnections(ctx context.Context) (res []byte, err error) {
254+
const cmd = "zos.admin.show_open_connections"
255+
256+
err = n.bus.Call(ctx, n.nodeTwin, cmd, nil, &res)
257+
return
258+
}
259+
260+
// AdminStopWorkload stops a workload
261+
func (n *NodeClient) AdminStopWorkload(ctx context.Context, twinID uint32, wlID uint64) error {
262+
const cmd = "zos.admin.stop_workload"
263+
args := struct {
264+
TwinID uint32 `json:"twin_id"`
265+
WorkloadID uint64 `json:"workload_id"`
266+
}{
267+
TwinID: twinID,
268+
WorkloadID: wlID,
269+
}
270+
271+
return n.bus.Call(ctx, n.nodeTwin, cmd, args, nil)
272+
}
273+
274+
// AdminResumeWorkload stops a workload
275+
func (n *NodeClient) AdminResumeWorkload(ctx context.Context, twinID uint32, wlID uint64) error {
276+
const cmd = "zos.admin.resume_workload"
277+
args := struct {
278+
TwinID uint32 `json:"twin_id"`
279+
WorkloadID uint64 `json:"workload_id"`
280+
}{
281+
TwinID: twinID,
282+
WorkloadID: wlID,
283+
}
284+
285+
return n.bus.Call(ctx, n.nodeTwin, cmd, args, nil)
286+
}
287+
215288
// NetworkListPublicIPs list taken public IPs on the node
216289
func (n *NodeClient) NetworkListPublicIPs(ctx context.Context) ([]string, error) {
217290
const cmd = "zos.network.list_public_ips"

docs/manual/api.md

Lines changed: 87 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -151,13 +151,95 @@ it means it can act like an access node to user private networks
151151

152152
## Admin
153153

154-
The next set of commands are ONLY possible to be called by the `farmer` only.
154+
The next set of commands are ONLY possible to be called by the `farmer` owning the node.
155+
156+
### Reboot Node
157+
158+
| command |body| return|
159+
|---|---|---|
160+
| `zos.admin.reboot` | - | - |
161+
162+
Stops all services then reboots the node
163+
164+
### Restart Service
165+
166+
| command |body| return|
167+
|---|---|---|
168+
| `zos.admin.restart` | string | - |
169+
170+
Restarts a service running on the node
171+
172+
### Restart All Services
173+
174+
| command |body| return|
175+
|---|---|---|
176+
| `zos.admin.restart_all` | - | - |
177+
178+
Restarts all zinit services running on the node
179+
180+
### Show Logs
181+
182+
| command |body| return|
183+
|---|---|---|
184+
| `zos.admin.show_logs` | int | []byte |
185+
186+
Shows a number of lines of zinit logs
187+
188+
### Show Resolve
189+
190+
| command |body| return|
191+
|---|---|---|
192+
| `zos.admin.show_resolve` | - | []byte |
193+
194+
Shows the content of /etc/resolv.conf
195+
196+
### Show Open Connections
197+
198+
| command |body| return|
199+
|---|---|---|
200+
| `zos.admin.show_open_connections` | - | []byte |
201+
202+
Shows information about all open connections in the node
203+
204+
### Stop Workload
205+
206+
| command |body| return|
207+
|---|---|---|
208+
| `zos.admin.Stop` | `Args` | - |
209+
210+
Where
211+
212+
```json
213+
Args {
214+
"twin_id": "uint32",
215+
"workload_id": "uint64",
216+
}
217+
```
218+
219+
Stops a workload
220+
221+
### Resume Workload
222+
223+
| command |body| return|
224+
|---|---|---|
225+
| `zos.admin.resume` | `Args` | - |
226+
227+
Where
228+
229+
```json
230+
Args {
231+
"twin_id": "uint32",
232+
"workload_id": "uint64",
233+
}
234+
```
235+
236+
Resumes a stopped workload
155237

156238
### List Physical Interfaces
157239

158240
| command |body| return|
159241
|---|---|---|
160-
| `zos.network.admin.interfaces` | - |`map[string]Interface` |
242+
| `zos.admin.interfaces` | - |`map[string]Interface` |
161243

162244
Where
163245

@@ -175,7 +257,7 @@ Those interfaces then can be used as an input to `set_public_nic`
175257

176258
| command |body| return|
177259
|---|---|---|
178-
| `zos.network.admin.get_public_nic` | - |`ExitDevice` |
260+
| `zos.admin.get_public_nic` | - |`ExitDevice` |
179261

180262
Where
181263

@@ -193,9 +275,9 @@ returns the interface used by public traffic (for user workloads)
193275

194276
| command |body| return|
195277
|---|---|---|
196-
| `zos.network.admin.set_public_nic` | `name` |- |
278+
| `zos.admin.set_public_nic` | `name` |- |
197279

198-
name must be one of (free) names returned by `zos.network.admin.interfaces`
280+
name must be one of (free) names returned by `zos.admin.interfaces`
199281

200282
## System
201283

@@ -223,7 +305,6 @@ name must be one of (free) names returned by `zos.network.admin.interfaces`
223305
|---|---|---|
224306
| `zos.system.node_features_get` | - |`[]NodeFeature` |
225307

226-
227308
Where
228309

229310
```json

pkg/zos_api/admin.go

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ import (
44
"context"
55
"encoding/json"
66
"fmt"
7+
"os"
8+
"path/filepath"
9+
10+
"github.com/rs/zerolog/log"
11+
"github.com/threefoldtech/zosbase/pkg/zinit"
712
)
813

914
func (g *ZosAPI) adminInterfacesHandler(ctx context.Context, payload []byte) (interface{}, error) {
@@ -45,3 +50,84 @@ func (g *ZosAPI) adminSetPublicNICHandler(ctx context.Context, payload []byte) (
4550
}
4651
return nil, g.networkerStub.SetPublicExitDevice(ctx, iface)
4752
}
53+
54+
func (g *ZosAPI) adminRebootHandler(ctx context.Context, payload []byte) (interface{}, error) {
55+
zinit := zinit.Default()
56+
57+
return nil, zinit.Reboot()
58+
}
59+
60+
func (g *ZosAPI) adminRestartServiceHandler(ctx context.Context, payload []byte) (interface{}, error) {
61+
var service string
62+
if err := json.Unmarshal(payload, &service); err != nil {
63+
return nil, fmt.Errorf("failed to decode input, expecting string: %w", err)
64+
}
65+
66+
zinit := zinit.Default()
67+
68+
return nil, zinit.Restart(service)
69+
}
70+
71+
func (g *ZosAPI) adminRestartAllHandler(ctx context.Context, payload []byte) (interface{}, error) {
72+
zinit := zinit.Default()
73+
74+
services, err := zinit.List()
75+
if err != nil {
76+
return nil, fmt.Errorf("failed to list node services, expecting string: %w", err)
77+
}
78+
79+
for service := range services {
80+
log.Debug().Str("service", service).Send()
81+
if err := zinit.Restart(service); err != nil {
82+
return nil, fmt.Errorf("failed to reboot service %s, expecting string: %w", service, err)
83+
}
84+
}
85+
86+
return nil, nil
87+
}
88+
89+
func (g *ZosAPI) adminShowLogsHandler(ctx context.Context, payload []byte) (interface{}, error) {
90+
var n int
91+
if err := json.Unmarshal(payload, &n); err != nil {
92+
return nil, fmt.Errorf("failed to decode input, expecting string: %w", err)
93+
}
94+
95+
zinit := zinit.Default()
96+
97+
return zinit.Log(n)
98+
}
99+
100+
func (g *ZosAPI) adminShowResolveHandler(ctx context.Context, payload []byte) (interface{}, error) {
101+
path := filepath.Join("/etc", "resolv.conf")
102+
return os.ReadFile(path)
103+
}
104+
105+
func (g *ZosAPI) adminShowOpenConnectionsHandler(ctx context.Context, payload []byte) (interface{}, error) {
106+
return g.statisticsStub.OpenConnections(ctx)
107+
}
108+
109+
func (g *ZosAPI) adminStopWorkloadHandler(ctx context.Context, payload []byte) (interface{}, error) {
110+
var args struct {
111+
TwinID uint32 `json:"twin_id"`
112+
WorkloadID uint64 `json:"workload_id"`
113+
}
114+
115+
if err := json.Unmarshal(payload, &args); err != nil {
116+
return nil, fmt.Errorf("failed to decode input, expecting twin id and workload id: %w", err)
117+
}
118+
119+
return nil, g.provisionStub.Pause(ctx, args.TwinID, args.WorkloadID)
120+
}
121+
122+
func (g *ZosAPI) adminResumeWorkloadHandler(ctx context.Context, payload []byte) (interface{}, error) {
123+
var args struct {
124+
TwinID uint32 `json:"twin_id"`
125+
WorkloadID uint64 `json:"workload_id"`
126+
}
127+
128+
if err := json.Unmarshal(payload, &args); err != nil {
129+
return nil, fmt.Errorf("failed to decode input, expecting twin id and workload id: %w", err)
130+
}
131+
132+
return nil, g.provisionStub.Resume(ctx, args.TwinID, args.WorkloadID)
133+
}

pkg/zos_api/routes.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,17 @@ func (g *ZosAPI) SetupRoutes(router *peer.Router) {
4949
admin.WithHandler("set_public_nic", g.adminSetPublicNICHandler)
5050
admin.WithHandler("get_public_nic", g.adminGetPublicNICHandler)
5151

52+
admin.WithHandler("reboot", g.adminRebootHandler)
53+
admin.WithHandler("restart", g.adminRestartServiceHandler)
54+
admin.WithHandler("restart_all", g.adminRestartAllHandler)
55+
56+
admin.WithHandler("show_logs", g.adminShowLogsHandler)
57+
admin.WithHandler("show_resolve", g.adminShowResolveHandler)
58+
admin.WithHandler("show_open_connections", g.adminShowOpenConnectionsHandler)
59+
60+
admin.WithHandler("stop_workload", g.adminStopWorkloadHandler)
61+
admin.WithHandler("resume_workload", g.adminResumeWorkloadHandler)
62+
5263
location := root.SubRoute("location")
5364
location.WithHandler("get", g.locationGet)
5465

0 commit comments

Comments
 (0)