SEBA-580 Add backup commands;
Retrieve server version;
Show available models
Change-Id: I3dc37d6f155661a2635fb4c95cf42b2aa81035e8
diff --git a/commands/transfer_handler.go b/commands/transfer_handler.go
new file mode 100644
index 0000000..0fce0f6
--- /dev/null
+++ b/commands/transfer_handler.go
@@ -0,0 +1,144 @@
+/*
+ * Portions copyright 2019-present Open Networking Foundation
+ * Original copyright 2019-present Ciena Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package commands
+
+import (
+ "context"
+ "crypto/sha1"
+ "github.com/fullstorydev/grpcurl"
+ "github.com/golang/protobuf/proto"
+ "github.com/jhump/protoreflect/dynamic"
+ "google.golang.org/grpc"
+ "hash"
+ "io"
+ "os"
+)
+
+/* Handlers for streaming upload and download */
+
+type DownloadHandler struct {
+ RpcEventHandler
+ f *os.File
+ chunks int
+ bytes int
+ status string
+ hash hash.Hash
+}
+
+type UploadHandler struct {
+ RpcEventHandler
+ chunksize int
+ f *os.File
+ uri string
+}
+
+func (h *DownloadHandler) OnReceiveResponse(m proto.Message) {
+ d, err := dynamic.AsDynamicMessage(m)
+ if err != nil {
+ h.status = "ERROR"
+ // TODO(smbaker): How to raise an exception?
+ return
+ }
+ chunk := d.GetFieldByName("chunk").(string)
+ io.WriteString(h.hash, chunk)
+ h.f.Write([]byte(chunk))
+ h.chunks += 1
+ h.bytes += len(chunk)
+}
+
+func (h *UploadHandler) GetParams(msg proto.Message) error {
+ dmsg, err := dynamic.AsDynamicMessage(msg)
+ if err != nil {
+ return err
+ }
+
+ //fmt.Printf("streamer, MessageName: %s\n", dmsg.XXX_MessageName())
+
+ block := make([]byte, h.chunksize)
+ bytes_read, err := h.f.Read(block)
+
+ if err == io.EOF {
+ h.f.Close()
+ //fmt.Print("EOF\n")
+ return err
+ }
+
+ if err != nil {
+ //fmt.Print("ERROR!\n")
+ return err
+ }
+
+ dmsg.TrySetFieldByName("uri", h.uri)
+ dmsg.TrySetFieldByName("chunk", string(block[:bytes_read]))
+
+ return nil
+}
+
+func UploadFile(conn *grpc.ClientConn, descriptor grpcurl.DescriptorSource, local_name string, uri string, chunkSize int) (*dynamic.Message, error) {
+ ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.Grpc.Timeout)
+ defer cancel()
+
+ headers := GenerateHeaders()
+
+ f, err := os.Open(local_name)
+ if err != nil {
+ return nil, err
+ }
+
+ h := &UploadHandler{uri: uri, f: f, chunksize: chunkSize}
+
+ err = grpcurl.InvokeRPC(ctx, descriptor, conn, "xos.filetransfer/Upload", headers, h, h.GetParams)
+ if err != nil {
+ return nil, err
+ }
+ d, err := dynamic.AsDynamicMessage(h.Response)
+ if err != nil {
+ return nil, err
+ }
+
+ return d, err
+}
+
+func DownloadFile(conn *grpc.ClientConn, descriptor grpcurl.DescriptorSource, uri string, local_name string) (*DownloadHandler, error) {
+ ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.Grpc.Timeout)
+ defer cancel()
+
+ headers := GenerateHeaders()
+
+ f, err := os.Create(local_name)
+ if err != nil {
+ return nil, err
+ }
+
+ dm := make(map[string]interface{})
+ dm["uri"] = uri
+
+ h := &DownloadHandler{
+ RpcEventHandler: RpcEventHandler{
+ Fields: map[string]map[string]interface{}{"xos.FileRequest": dm},
+ },
+ f: f,
+ hash: sha1.New(),
+ status: "SUCCESS"}
+
+ err = grpcurl.InvokeRPC(ctx, descriptor, conn, "xos.filetransfer/Download", headers, h, h.GetParams)
+ if err != nil {
+ return nil, err
+ }
+
+ return h, err
+}