From: Adam Malinowski Date: Tue, 28 Nov 2017 14:31:28 +0000 (+0100) Subject: Add file transfer functions to SessionProvider X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ceaaba4b362489d10c761b0dca969a31f65e48f7;p=tools%2Fweles.git Add file transfer functions to SessionProvider Change-Id: Ief14d76d93bfd041bc9809d0599719859fde69dc Signed-off-by: Adam Malinowski --- diff --git a/manager/dryad/dryad.go b/manager/dryad/dryad.go index 3af47aa..3a3452a 100644 --- a/manager/dryad/dryad.go +++ b/manager/dryad/dryad.go @@ -45,6 +45,12 @@ type SessionProvider interface { // Close terminates session to Dryad. Close() error + + // SendFile sends file to Dryad. + SendFile(src, dst string) error + + // ReceiveFile receives file from Dryad. + ReceiveFile(src, dst string) error } // Credentials are used to login to device. diff --git a/manager/dryad/dryad_session_provider.go b/manager/dryad/dryad_session_provider.go index 19e2657..bdcc83b 100644 --- a/manager/dryad/dryad_session_provider.go +++ b/manager/dryad/dryad_session_provider.go @@ -18,14 +18,15 @@ package dryad import ( "bytes" - "time" - + "fmt" + "io" + "os" + "path/filepath" "strings" + "time" "crypto/rsa" - "fmt" - . "git.tizen.org/tools/weles" "golang.org/x/crypto/ssh" ) @@ -163,3 +164,100 @@ func (d *sessionProvider) Close() error { d.connection.client = nil return err } + +// SendFile is a part of SessionProvider interface. +func (d *sessionProvider) SendFile(src, dst string) error { + f, err := os.Open(src) + if err != nil { + return err + } + defer f.Close() + + s, err := f.Stat() + if err != nil { + return err + } + + session, err := d.newSession() + if err != nil { + return err + } + defer session.Close() + + filename := filepath.Base(dst) + directory := filepath.Dir(dst) + + w, err := session.StdinPipe() + if err != nil { + return err + } + defer w.Close() + + var stdout, stderr bytes.Buffer + session.Stdout = &stdout + session.Stderr = &stderr + + // Trigger SCP sink mode + err = session.Start("scp -t " + directory) + if err != nil { + return err + } + + _, err = fmt.Fprintln(w, "C0755", s.Size(), filename) + if err != nil { + return err + } + + _, err = io.Copy(w, f) + if err != nil { + return err + } + + _, err = fmt.Fprintln(w, "\x00") + if err != nil { + return err + } + + err = session.Wait() + + // FIXME: unexpected is reported by scp every time the transfer is finished properly. Needs to be solved. + // Bellow we have a very lousy trick. I hope it will be fixed in the future. + // I don't know what is the reason or how to fix it. Has to wait a little bit. Or maybe someone else will find the solution. + // First candidate sshfs -o slave + if strings.Contains(stdout.String(), "unexpected ") { + return nil + } + return err +} + +// ReceiveFile is a part of SessionProvider interface. +func (d *sessionProvider) ReceiveFile(src, dst string) error { + session, err := d.newSession() + if err != nil { + return err + } + defer session.Close() + + r, err := session.StdoutPipe() + if err != nil { + return err + } + + file, err := os.Create(dst) + if err != nil { + return err + } + defer file.Close() + + err = session.Start("scp " + src + " /dev/stdout") + if err != nil { + return err + } + + _, err = io.Copy(file, r) + if err != nil { + return err + } + + return session.Wait() +} diff --git a/manager/dryad/dryad_session_provider_test.go b/manager/dryad/dryad_session_provider_test.go index 48c30c6..2284451 100644 --- a/manager/dryad/dryad_session_provider_test.go +++ b/manager/dryad/dryad_session_provider_test.go @@ -69,4 +69,24 @@ var _ = Describe("SessionProvider", func() { It("should switch to TS", func() { Expect(sp.TS()).ToNot(HaveOccurred()) }) + + It("should transfer file to Dryad", func() { + err := sp.SendFile(keyFile, "/tmp/"+keyFile) + Expect(err).ToNot(HaveOccurred()) + }) + + It("should not transfer file to Dryad - insufficient permissions", func() { + err := sp.SendFile(keyFile, "/root/"+keyFile) + Expect(err).To(HaveOccurred()) + }) + + It("should transfer file from Dryad", func() { + err := sp.ReceiveFile("/tmp/"+keyFile, "/tmp/dl-"+keyFile) + Expect(err).ToNot(HaveOccurred()) + }) + + It("should not transfer nonexistent file from Dryad", func() { + err := sp.ReceiveFile("/tmp/"+keyFile+"noway", "/tmp/dl-"+keyFile) + Expect(err).To(HaveOccurred()) + }) }) diff --git a/manager/dryad_job_runner_test.go b/manager/dryad_job_runner_test.go index e91ae57..d74a027 100644 --- a/manager/dryad_job_runner_test.go +++ b/manager/dryad_job_runner_test.go @@ -16,6 +16,8 @@ package manager +//go:generate mockgen -package=manager -destination=mock_dryad_test.go git.tizen.org/tools/weles/manager/dryad SessionProvider,DeviceCommunicationProvider + import ( "context" "errors" diff --git a/manager/mock_dryad_test.go b/manager/mock_dryad_test.go index c650111..3309594 100644 --- a/manager/mock_dryad_test.go +++ b/manager/mock_dryad_test.go @@ -1,5 +1,5 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: manager/dryad/dryad.go +// Source: git.tizen.org/tools/weles/manager/dryad (interfaces: SessionProvider,DeviceCommunicationProvider) // Package manager is a generated GoMock package. package manager @@ -34,18 +34,16 @@ func (m *MockSessionProvider) EXPECT() *MockSessionProviderMockRecorder { return m.recorder } -// Exec mocks base method -func (m *MockSessionProvider) Exec(cmd []string) ([]byte, []byte, error) { - ret := m.ctrl.Call(m, "Exec", cmd) - ret0, _ := ret[0].([]byte) - ret1, _ := ret[1].([]byte) - ret2, _ := ret[2].(error) - return ret0, ret1, ret2 +// Close mocks base method +func (m *MockSessionProvider) Close() error { + ret := m.ctrl.Call(m, "Close") + ret0, _ := ret[0].(error) + return ret0 } -// Exec indicates an expected call of Exec -func (mr *MockSessionProviderMockRecorder) Exec(cmd interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Exec", reflect.TypeOf((*MockSessionProvider)(nil).Exec), cmd) +// Close indicates an expected call of Close +func (mr *MockSessionProviderMockRecorder) Close() *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockSessionProvider)(nil).Close)) } // DUT mocks base method @@ -60,16 +58,18 @@ func (mr *MockSessionProviderMockRecorder) DUT() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DUT", reflect.TypeOf((*MockSessionProvider)(nil).DUT)) } -// TS mocks base method -func (m *MockSessionProvider) TS() error { - ret := m.ctrl.Call(m, "TS") - ret0, _ := ret[0].(error) - return ret0 +// Exec mocks base method +func (m *MockSessionProvider) Exec(arg0 []string) ([]byte, []byte, error) { + ret := m.ctrl.Call(m, "Exec", arg0) + ret0, _ := ret[0].([]byte) + ret1, _ := ret[1].([]byte) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 } -// TS indicates an expected call of TS -func (mr *MockSessionProviderMockRecorder) TS() *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TS", reflect.TypeOf((*MockSessionProvider)(nil).TS)) +// Exec indicates an expected call of Exec +func (mr *MockSessionProviderMockRecorder) Exec(arg0 interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Exec", reflect.TypeOf((*MockSessionProvider)(nil).Exec), arg0) } // PowerTick mocks base method @@ -84,16 +84,40 @@ func (mr *MockSessionProviderMockRecorder) PowerTick() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PowerTick", reflect.TypeOf((*MockSessionProvider)(nil).PowerTick)) } -// Close mocks base method -func (m *MockSessionProvider) Close() error { - ret := m.ctrl.Call(m, "Close") +// ReceiveFile mocks base method +func (m *MockSessionProvider) ReceiveFile(arg0, arg1 string) error { + ret := m.ctrl.Call(m, "ReceiveFile", arg0, arg1) ret0, _ := ret[0].(error) return ret0 } -// Close indicates an expected call of Close -func (mr *MockSessionProviderMockRecorder) Close() *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockSessionProvider)(nil).Close)) +// ReceiveFile indicates an expected call of ReceiveFile +func (mr *MockSessionProviderMockRecorder) ReceiveFile(arg0, arg1 interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReceiveFile", reflect.TypeOf((*MockSessionProvider)(nil).ReceiveFile), arg0, arg1) +} + +// SendFile mocks base method +func (m *MockSessionProvider) SendFile(arg0, arg1 string) error { + ret := m.ctrl.Call(m, "SendFile", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// SendFile indicates an expected call of SendFile +func (mr *MockSessionProviderMockRecorder) SendFile(arg0, arg1 interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendFile", reflect.TypeOf((*MockSessionProvider)(nil).SendFile), arg0, arg1) +} + +// TS mocks base method +func (m *MockSessionProvider) TS() error { + ret := m.ctrl.Call(m, "TS") + ret0, _ := ret[0].(error) + return ret0 +} + +// TS indicates an expected call of TS +func (mr *MockSessionProviderMockRecorder) TS() *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TS", reflect.TypeOf((*MockSessionProvider)(nil).TS)) } // MockDeviceCommunicationProvider is a mock of DeviceCommunicationProvider interface @@ -119,45 +143,45 @@ func (m *MockDeviceCommunicationProvider) EXPECT() *MockDeviceCommunicationProvi return m.recorder } -// Login mocks base method -func (m *MockDeviceCommunicationProvider) Login(arg0 dryad.Credentials) error { - ret := m.ctrl.Call(m, "Login", arg0) +// Close mocks base method +func (m *MockDeviceCommunicationProvider) Close() error { + ret := m.ctrl.Call(m, "Close") ret0, _ := ret[0].(error) return ret0 } -// Login indicates an expected call of Login -func (mr *MockDeviceCommunicationProviderMockRecorder) Login(arg0 interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Login", reflect.TypeOf((*MockDeviceCommunicationProvider)(nil).Login), arg0) +// Close indicates an expected call of Close +func (mr *MockDeviceCommunicationProviderMockRecorder) Close() *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockDeviceCommunicationProvider)(nil).Close)) } -// CopyFilesTo mocks base method -func (m *MockDeviceCommunicationProvider) CopyFilesTo(src []string, dest string) error { - ret := m.ctrl.Call(m, "CopyFilesTo", src, dest) +// CopyFilesFrom mocks base method +func (m *MockDeviceCommunicationProvider) CopyFilesFrom(arg0 []string, arg1 string) error { + ret := m.ctrl.Call(m, "CopyFilesFrom", arg0, arg1) ret0, _ := ret[0].(error) return ret0 } -// CopyFilesTo indicates an expected call of CopyFilesTo -func (mr *MockDeviceCommunicationProviderMockRecorder) CopyFilesTo(src, dest interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CopyFilesTo", reflect.TypeOf((*MockDeviceCommunicationProvider)(nil).CopyFilesTo), src, dest) +// CopyFilesFrom indicates an expected call of CopyFilesFrom +func (mr *MockDeviceCommunicationProviderMockRecorder) CopyFilesFrom(arg0, arg1 interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CopyFilesFrom", reflect.TypeOf((*MockDeviceCommunicationProvider)(nil).CopyFilesFrom), arg0, arg1) } -// CopyFilesFrom mocks base method -func (m *MockDeviceCommunicationProvider) CopyFilesFrom(src []string, dest string) error { - ret := m.ctrl.Call(m, "CopyFilesFrom", src, dest) +// CopyFilesTo mocks base method +func (m *MockDeviceCommunicationProvider) CopyFilesTo(arg0 []string, arg1 string) error { + ret := m.ctrl.Call(m, "CopyFilesTo", arg0, arg1) ret0, _ := ret[0].(error) return ret0 } -// CopyFilesFrom indicates an expected call of CopyFilesFrom -func (mr *MockDeviceCommunicationProviderMockRecorder) CopyFilesFrom(src, dest interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CopyFilesFrom", reflect.TypeOf((*MockDeviceCommunicationProvider)(nil).CopyFilesFrom), src, dest) +// CopyFilesTo indicates an expected call of CopyFilesTo +func (mr *MockDeviceCommunicationProviderMockRecorder) CopyFilesTo(arg0, arg1 interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CopyFilesTo", reflect.TypeOf((*MockDeviceCommunicationProvider)(nil).CopyFilesTo), arg0, arg1) } // Exec mocks base method -func (m *MockDeviceCommunicationProvider) Exec(cmd []string, timeout time.Duration) ([]byte, []byte, error) { - ret := m.ctrl.Call(m, "Exec", cmd, timeout) +func (m *MockDeviceCommunicationProvider) Exec(arg0 []string, arg1 time.Duration) ([]byte, []byte, error) { + ret := m.ctrl.Call(m, "Exec", arg0, arg1) ret0, _ := ret[0].([]byte) ret1, _ := ret[1].([]byte) ret2, _ := ret[2].(error) @@ -165,18 +189,18 @@ func (m *MockDeviceCommunicationProvider) Exec(cmd []string, timeout time.Durati } // Exec indicates an expected call of Exec -func (mr *MockDeviceCommunicationProviderMockRecorder) Exec(cmd, timeout interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Exec", reflect.TypeOf((*MockDeviceCommunicationProvider)(nil).Exec), cmd, timeout) +func (mr *MockDeviceCommunicationProviderMockRecorder) Exec(arg0, arg1 interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Exec", reflect.TypeOf((*MockDeviceCommunicationProvider)(nil).Exec), arg0, arg1) } -// Close mocks base method -func (m *MockDeviceCommunicationProvider) Close() error { - ret := m.ctrl.Call(m, "Close") +// Login mocks base method +func (m *MockDeviceCommunicationProvider) Login(arg0 dryad.Credentials) error { + ret := m.ctrl.Call(m, "Login", arg0) ret0, _ := ret[0].(error) return ret0 } -// Close indicates an expected call of Close -func (mr *MockDeviceCommunicationProviderMockRecorder) Close() *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockDeviceCommunicationProvider)(nil).Close)) +// Login indicates an expected call of Login +func (mr *MockDeviceCommunicationProviderMockRecorder) Login(arg0 interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Login", reflect.TypeOf((*MockDeviceCommunicationProvider)(nil).Login), arg0) }