Skip to content

Commit fcbdd55

Browse files
bibhuprasad-hclVSuryaprasad-HCL
authored andcommitted
[gNOI] Added dbus_client to gnoi Install RPC,Adding Activate & Verify RPC and Use transformer for TransferReady/TransferEnd,Added initial implementation of gNOI.OS Install RPC
1 parent db9afb6 commit fcbdd55

File tree

10 files changed

+710
-3
lines changed

10 files changed

+710
-3
lines changed

common_utils/context.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ const (
4343
GNMI_SET
4444
GNMI_SET_FAIL
4545
GNOI_REBOOT
46+
GNOI_OS_INSTALL
4647
DBUS
4748
DBUS_FAIL
4849
DBUS_APPLY_PATCH_DB
@@ -77,6 +78,8 @@ func (c CounterType) String() string {
7778
return "GNMI set fail"
7879
case GNOI_REBOOT:
7980
return "GNOI reboot"
81+
case GNOI_OS_INSTALL:
82+
return "GNOI OS Install"
8083
case DBUS:
8184
return "DBUS"
8285
case DBUS_FAIL:

gnmi_server/gnoi_os.go

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
package gnmi
2+
3+
import (
4+
"fmt"
5+
"io"
6+
"os"
7+
"sync"
8+
9+
ospb "github.com/openconfig/gnoi/os"
10+
11+
log "github.com/golang/glog"
12+
"google.golang.org/grpc/codes"
13+
"google.golang.org/grpc/status"
14+
)
15+
16+
var (
17+
sem sync.Mutex
18+
imgTrfInitiated = false
19+
)
20+
21+
func (srv *OSServer) processTransferReq(trfReq *ospb.TransferRequest) *ospb.InstallResponse {
22+
if trfReq.GetVersion() == "" {
23+
log.Errorln("TransferRequest must contain a valid OS version.")
24+
return &ospb.InstallResponse{
25+
Response: &ospb.InstallResponse_InstallError{
26+
InstallError: &ospb.InstallError{
27+
Type: ospb.InstallError_PARSE_FAIL,
28+
Detail: "TransferRequest must contain a valid OS version.",
29+
},
30+
},
31+
}
32+
}
33+
34+
return &ospb.InstallResponse{
35+
Response: &ospb.InstallResponse_TransferReady{},
36+
}
37+
}
38+
39+
func (srv *OSServer) processTransferEnd(trfReq *ospb.TransferEnd) *ospb.InstallResponse {
40+
return &ospb.InstallResponse{
41+
Response: &ospb.InstallResponse_Validated{},
42+
}
43+
}
44+
45+
func (srv *OSServer) processTransferContent(trfCnt []byte, imgPath string) *ospb.InstallResponse {
46+
// If image exists, target should have sent Validated | InstallError on TransferRequest.
47+
if !imgTrfInitiated && srv.imageExists(imgPath) {
48+
return &ospb.InstallResponse{
49+
Response: &ospb.InstallResponse_InstallError{
50+
InstallError: &ospb.InstallError{
51+
Detail: fmt.Sprintf("File exists [%s]!", imgPath),
52+
},
53+
},
54+
}
55+
}
56+
imgTrfInitiated = true
57+
58+
errResp := &ospb.InstallResponse{
59+
Response: &ospb.InstallResponse_InstallError{
60+
InstallError: &ospb.InstallError{
61+
Detail: fmt.Sprintf("Failed to open file [%s].", imgPath),
62+
},
63+
},
64+
}
65+
66+
// If the file doesn't exist, create it, or append to the file
67+
f, err := os.OpenFile(imgPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
68+
if err != nil {
69+
log.Errorln(err)
70+
return errResp
71+
}
72+
if _, err := f.Write(trfCnt); err != nil {
73+
f.Close()
74+
log.Errorln(err)
75+
return errResp
76+
}
77+
if err := f.Close(); err != nil {
78+
log.Errorln(err)
79+
return errResp
80+
}
81+
82+
return &ospb.InstallResponse{
83+
Response: &ospb.InstallResponse_TransferProgress{},
84+
}
85+
}
86+
87+
func (srv *OSServer) getVersionPath(version string) string {
88+
return srv.config.ImgDir + "/" + version
89+
}
90+
91+
func (srv *OSServer) imageExists(path string) bool {
92+
if _, err := os.Lstat(path); err == nil {
93+
return true
94+
}
95+
return false
96+
}
97+
98+
// Install implements correspondig RPC
99+
func (srv *OSServer) Install(stream ospb.OS_InstallServer) error {
100+
ctx := stream.Context()
101+
ctx, err := authenticate(srv.config, ctx, "gnoi", false)
102+
if err != nil {
103+
return err
104+
}
105+
log.V(1).Info("gNOI: os.Install")
106+
107+
defer func() {
108+
imgTrfInitiated = false
109+
}()
110+
111+
// Concurrent Install RPCs are not allowed.
112+
if !sem.TryLock() {
113+
log.Errorln("Concurrent Install RPCs are not allowed.")
114+
115+
// Send InstallError response.
116+
err = stream.Send(&ospb.InstallResponse{
117+
Response: &ospb.InstallResponse_InstallError{
118+
InstallError: &ospb.InstallError{
119+
Type: ospb.InstallError_INSTALL_IN_PROGRESS,
120+
Detail: "Concurrent Install RPCs are not allowed.",
121+
},
122+
},
123+
})
124+
if err != nil {
125+
log.Errorln("Error while sending InstallError response: ", err)
126+
return status.Errorf(codes.Aborted, err.Error())
127+
}
128+
129+
return status.Errorf(codes.Aborted, "Concurrent Install RPCs are not allowed.")
130+
}
131+
defer sem.Unlock()
132+
133+
// Receive TransferReq message.
134+
req, err := stream.Recv()
135+
if err == io.EOF {
136+
log.Errorln("Received EOF instead of TransferRequest!")
137+
return nil
138+
}
139+
if err != nil {
140+
log.Errorln("Received error: ", err)
141+
return status.Errorf(codes.Aborted, err.Error())
142+
}
143+
144+
trfReq := req.GetTransferRequest()
145+
if trfReq == nil {
146+
log.Errorln("Did not receive a TransferRequest.")
147+
return status.Errorf(codes.InvalidArgument, "Expected TransferRequest.")
148+
}
149+
150+
resp := srv.processTransferReq(trfReq)
151+
if resp != nil {
152+
if err := stream.Send(resp); err != nil {
153+
log.Errorln("Error while sending response: ", err)
154+
return status.Errorf(codes.Aborted, err.Error())
155+
}
156+
}
157+
if resp == nil || resp.GetInstallError() != nil {
158+
return status.Errorf(codes.Aborted, "Failed to process TransferRequest.")
159+
}
160+
161+
imgPath := srv.getVersionPath(trfReq.GetVersion())
162+
for {
163+
req, err = stream.Recv()
164+
if err == io.EOF {
165+
log.Errorln("Received EOF instead of TransferContent request!")
166+
return nil
167+
}
168+
if err != nil {
169+
log.Errorln("Received error: ", err)
170+
return status.Errorf(codes.Aborted, err.Error())
171+
}
172+
if trfReq := req.GetTransferRequest(); trfReq != nil {
173+
log.Errorln("Received a TransferReq out-of-sequence.")
174+
return status.Errorf(codes.InvalidArgument, "Expected TransferContent, or TransferEnd.")
175+
}
176+
// Transferring content is complete.
177+
if trfEnd := req.GetTransferEnd(); trfEnd != nil {
178+
break
179+
}
180+
// Process content transfer.
181+
resp := srv.processTransferContent(req.GetTransferContent(), imgPath)
182+
if resp != nil {
183+
if err := stream.Send(resp); err != nil {
184+
log.Errorln("Error while sending response: ", err)
185+
return status.Errorf(codes.Aborted, err.Error())
186+
}
187+
}
188+
if resp == nil || resp.GetInstallError() != nil {
189+
return status.Errorf(codes.Aborted, "Failed to process TransferContent.")
190+
}
191+
}
192+
193+
// Receive TransferEnd message.
194+
trfEnd := req.GetTransferEnd()
195+
if trfEnd == nil {
196+
log.Errorln("Did not receive a TransferEnd")
197+
return status.Errorf(codes.InvalidArgument, "Expected TransferEnd")
198+
}
199+
200+
resp = srv.processTransferEnd(trfEnd)
201+
if resp != nil {
202+
if err := stream.Send(resp); err != nil {
203+
log.Errorln("Error while sending response: ", err)
204+
return status.Errorf(codes.Aborted, err.Error())
205+
}
206+
}
207+
if resp == nil || resp.GetInstallError() != nil {
208+
return status.Errorf(codes.Aborted, "Failed to process TransferEnd.")
209+
}
210+
211+
return nil
212+
}

0 commit comments

Comments
 (0)