Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
OpenDAS
nni
Commits
1328f412
Unverified
Commit
1328f412
authored
Dec 10, 2019
by
chicm-ms
Committed by
GitHub
Dec 10, 2019
Browse files
Fix eslint errors (#1836)
* update eslint rules * auto fix eslint * manually fix eslint (#1833)
parent
8c07cf41
Changes
42
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
59 additions
and
70 deletions
+59
-70
src/nni_manager/training_service/remote_machine/remoteMachineTrainingService.ts
...ng_service/remote_machine/remoteMachineTrainingService.ts
+22
-31
src/nni_manager/training_service/remote_machine/sshClientUtility.ts
...nager/training_service/remote_machine/sshClientUtility.ts
+37
-39
No files found.
src/nni_manager/training_service/remote_machine/remoteMachineTrainingService.ts
View file @
1328f412
...
@@ -4,12 +4,10 @@
...
@@ -4,12 +4,10 @@
'
use strict
'
;
'
use strict
'
;
import
*
as
assert
from
'
assert
'
;
import
*
as
assert
from
'
assert
'
;
import
*
as
cpp
from
'
child-process-promise
'
;
import
{
EventEmitter
}
from
'
events
'
;
import
{
EventEmitter
}
from
'
events
'
;
import
*
as
fs
from
'
fs
'
;
import
*
as
fs
from
'
fs
'
;
import
*
as
os
from
'
os
'
;
import
*
as
path
from
'
path
'
;
import
*
as
path
from
'
path
'
;
import
{
Client
,
ConnectConfig
}
from
'
ssh2
'
;
import
{
Client
}
from
'
ssh2
'
;
import
{
Deferred
}
from
'
ts-deferred
'
;
import
{
Deferred
}
from
'
ts-deferred
'
;
import
{
String
}
from
'
typescript-string-operations
'
;
import
{
String
}
from
'
typescript-string-operations
'
;
import
*
as
component
from
'
../../common/component
'
;
import
*
as
component
from
'
../../common/component
'
;
...
@@ -29,12 +27,12 @@ import { CONTAINER_INSTALL_NNI_SHELL_FORMAT } from '../common/containerJobData';
...
@@ -29,12 +27,12 @@ import { CONTAINER_INSTALL_NNI_SHELL_FORMAT } from '../common/containerJobData';
import
{
GPUSummary
}
from
'
../common/gpuData
'
;
import
{
GPUSummary
}
from
'
../common/gpuData
'
;
import
{
TrialConfig
}
from
'
../common/trialConfig
'
;
import
{
TrialConfig
}
from
'
../common/trialConfig
'
;
import
{
TrialConfigMetadataKey
}
from
'
../common/trialConfigMetadataKey
'
;
import
{
TrialConfigMetadataKey
}
from
'
../common/trialConfigMetadataKey
'
;
import
{
execCopydir
,
execMkdir
,
execRemove
,
validateCodeDir
,
getGpuMetricsCollectorBashScriptContent
}
from
'
../common/util
'
;
import
{
execCopydir
,
execMkdir
,
validateCodeDir
,
getGpuMetricsCollectorBashScriptContent
}
from
'
../common/util
'
;
import
{
GPUScheduler
}
from
'
./gpuScheduler
'
;
import
{
GPUScheduler
}
from
'
./gpuScheduler
'
;
import
{
import
{
HOST_JOB_SHELL_FORMAT
,
RemoteCommandResult
,
REMOTEMACHINE_TRIAL_COMMAND_FORMAT
,
RemoteMachineMeta
,
RemoteCommandResult
,
REMOTEMACHINE_TRIAL_COMMAND_FORMAT
,
RemoteMachineMeta
,
RemoteMachineScheduleInfo
,
RemoteMachineScheduleResult
,
RemoteMachineTrialJobDetail
,
RemoteMachineScheduleInfo
,
RemoteMachineScheduleResult
,
RemoteMachineTrialJobDetail
,
ScheduleResultType
,
SSHClient
,
SSHClientManager
ScheduleResultType
,
SSHClientManager
}
from
'
./remoteMachineData
'
;
}
from
'
./remoteMachineData
'
;
import
{
RemoteMachineJobRestServer
}
from
'
./remoteMachineJobRestServer
'
;
import
{
RemoteMachineJobRestServer
}
from
'
./remoteMachineJobRestServer
'
;
import
{
SSHClientUtility
}
from
'
./sshClientUtility
'
;
import
{
SSHClientUtility
}
from
'
./sshClientUtility
'
;
...
@@ -93,7 +91,7 @@ class RemoteMachineTrainingService implements TrainingService {
...
@@ -93,7 +91,7 @@ class RemoteMachineTrainingService implements TrainingService {
while
(
this
.
jobQueue
.
length
>
0
)
{
while
(
this
.
jobQueue
.
length
>
0
)
{
this
.
updateGpuReservation
();
this
.
updateGpuReservation
();
const
trialJobId
:
string
=
this
.
jobQueue
[
0
];
const
trialJobId
:
string
=
this
.
jobQueue
[
0
];
const
prepareResult
:
boolean
=
await
this
.
prepareTrialJob
(
trialJobId
);
const
prepareResult
:
boolean
=
await
this
.
prepareTrialJob
(
trialJobId
);
if
(
prepareResult
)
{
if
(
prepareResult
)
{
// Remove trial job with trialJobId from job queue
// Remove trial job with trialJobId from job queue
this
.
jobQueue
.
shift
();
this
.
jobQueue
.
shift
();
...
@@ -241,12 +239,7 @@ class RemoteMachineTrainingService implements TrainingService {
...
@@ -241,12 +239,7 @@ class RemoteMachineTrainingService implements TrainingService {
if
(
trialJobDetail
===
undefined
)
{
if
(
trialJobDetail
===
undefined
)
{
throw
new
Error
(
`updateTrialJob failed:
${
trialJobId
}
not found`
);
throw
new
Error
(
`updateTrialJob failed:
${
trialJobId
}
not found`
);
}
}
const
rmMeta
:
RemoteMachineMeta
|
undefined
=
(
<
RemoteMachineTrialJobDetail
>
trialJobDetail
).
rmMeta
;
await
this
.
writeParameterFile
(
trialJobId
,
form
.
hyperParameters
);
if
(
rmMeta
!==
undefined
)
{
await
this
.
writeParameterFile
(
trialJobId
,
form
.
hyperParameters
,
rmMeta
);
}
else
{
throw
new
Error
(
`updateTrialJob failed:
${
trialJobId
}
rmMeta not found`
);
}
return
trialJobDetail
;
return
trialJobDetail
;
}
}
...
@@ -272,7 +265,7 @@ class RemoteMachineTrainingService implements TrainingService {
...
@@ -272,7 +265,7 @@ class RemoteMachineTrainingService implements TrainingService {
}
}
// Remove the job with trialJobId from job queue
// Remove the job with trialJobId from job queue
const
index
:
number
=
this
.
jobQueue
.
indexOf
(
trialJobId
);
const
index
:
number
=
this
.
jobQueue
.
indexOf
(
trialJobId
);
if
(
index
>=
0
)
{
if
(
index
>=
0
)
{
this
.
jobQueue
.
splice
(
index
,
1
);
this
.
jobQueue
.
splice
(
index
,
1
);
}
}
...
@@ -319,7 +312,7 @@ class RemoteMachineTrainingService implements TrainingService {
...
@@ -319,7 +312,7 @@ class RemoteMachineTrainingService implements TrainingService {
await
this
.
setupConnections
(
value
);
await
this
.
setupConnections
(
value
);
this
.
gpuScheduler
=
new
GPUScheduler
(
this
.
machineSSHClientMap
);
this
.
gpuScheduler
=
new
GPUScheduler
(
this
.
machineSSHClientMap
);
break
;
break
;
case
TrialConfigMetadataKey
.
TRIAL_CONFIG
:
case
TrialConfigMetadataKey
.
TRIAL_CONFIG
:
{
const
remoteMachineTrailConfig
:
TrialConfig
=
<
TrialConfig
>
JSON
.
parse
(
value
);
const
remoteMachineTrailConfig
:
TrialConfig
=
<
TrialConfig
>
JSON
.
parse
(
value
);
// Parse trial config failed, throw Error
// Parse trial config failed, throw Error
if
(
remoteMachineTrailConfig
===
undefined
)
{
if
(
remoteMachineTrailConfig
===
undefined
)
{
...
@@ -343,6 +336,7 @@ class RemoteMachineTrainingService implements TrainingService {
...
@@ -343,6 +336,7 @@ class RemoteMachineTrainingService implements TrainingService {
this
.
trialConfig
=
remoteMachineTrailConfig
;
this
.
trialConfig
=
remoteMachineTrailConfig
;
break
;
break
;
}
case
TrialConfigMetadataKey
.
MULTI_PHASE
:
case
TrialConfigMetadataKey
.
MULTI_PHASE
:
this
.
isMultiPhase
=
(
value
===
'
true
'
||
value
===
'
True
'
);
this
.
isMultiPhase
=
(
value
===
'
true
'
||
value
===
'
True
'
);
break
;
break
;
...
@@ -464,7 +458,7 @@ class RemoteMachineTrainingService implements TrainingService {
...
@@ -464,7 +458,7 @@ class RemoteMachineTrainingService implements TrainingService {
}
}
private
async
prepareTrialJob
(
trialJobId
:
string
):
Promise
<
boolean
>
{
private
async
prepareTrialJob
(
trialJobId
:
string
):
Promise
<
boolean
>
{
const
deferred
:
Deferred
<
boolean
>
=
new
Deferred
<
boolean
>
();
const
deferred
:
Deferred
<
boolean
>
=
new
Deferred
<
boolean
>
();
if
(
this
.
trialConfig
===
undefined
)
{
if
(
this
.
trialConfig
===
undefined
)
{
throw
new
Error
(
'
trial config is not initialized
'
);
throw
new
Error
(
'
trial config is not initialized
'
);
...
@@ -485,13 +479,13 @@ class RemoteMachineTrainingService implements TrainingService {
...
@@ -485,13 +479,13 @@ class RemoteMachineTrainingService implements TrainingService {
// get an ssh client from scheduler
// get an ssh client from scheduler
const
rmScheduleResult
:
RemoteMachineScheduleResult
=
this
.
gpuScheduler
.
scheduleMachine
(
this
.
trialConfig
.
gpuNum
,
trialJobDetail
);
const
rmScheduleResult
:
RemoteMachineScheduleResult
=
this
.
gpuScheduler
.
scheduleMachine
(
this
.
trialConfig
.
gpuNum
,
trialJobDetail
);
if
(
rmScheduleResult
.
resultType
===
ScheduleResultType
.
REQUIRE_EXCEED_TOTAL
)
{
if
(
rmScheduleResult
.
resultType
===
ScheduleResultType
.
REQUIRE_EXCEED_TOTAL
)
{
const
errorMessage
:
string
=
`Required GPU number
${
this
.
trialConfig
.
gpuNum
}
is too large, no machine can meet`
;
const
errorMessage
:
string
=
`Required GPU number
${
this
.
trialConfig
.
gpuNum
}
is too large, no machine can meet`
;
this
.
log
.
error
(
errorMessage
);
this
.
log
.
error
(
errorMessage
);
deferred
.
reject
();
deferred
.
reject
();
throw
new
NNIError
(
NNIErrorNames
.
RESOURCE_NOT_AVAILABLE
,
errorMessage
);
throw
new
NNIError
(
NNIErrorNames
.
RESOURCE_NOT_AVAILABLE
,
errorMessage
);
}
else
if
(
rmScheduleResult
.
resultType
===
ScheduleResultType
.
SUCCEED
}
else
if
(
rmScheduleResult
.
resultType
===
ScheduleResultType
.
SUCCEED
&&
rmScheduleResult
.
scheduleInfo
!==
undefined
)
{
&&
rmScheduleResult
.
scheduleInfo
!==
undefined
)
{
const
rmScheduleInfo
:
RemoteMachineScheduleInfo
=
rmScheduleResult
.
scheduleInfo
;
const
rmScheduleInfo
:
RemoteMachineScheduleInfo
=
rmScheduleResult
.
scheduleInfo
;
const
trialWorkingFolder
:
string
=
unixPathJoin
(
this
.
remoteExpRootDir
,
'
trials
'
,
trialJobId
);
const
trialWorkingFolder
:
string
=
unixPathJoin
(
this
.
remoteExpRootDir
,
'
trials
'
,
trialJobId
);
trialJobDetail
.
rmMeta
=
rmScheduleInfo
.
rmMeta
;
trialJobDetail
.
rmMeta
=
rmScheduleInfo
.
rmMeta
;
...
@@ -521,7 +515,7 @@ class RemoteMachineTrainingService implements TrainingService {
...
@@ -521,7 +515,7 @@ class RemoteMachineTrainingService implements TrainingService {
if
(
this
.
trialConfig
===
undefined
)
{
if
(
this
.
trialConfig
===
undefined
)
{
throw
new
Error
(
'
trial config is not initialized
'
);
throw
new
Error
(
'
trial config is not initialized
'
);
}
}
const
cuda
_v
isible
_d
evice
:
string
=
rmScheduleInfo
.
cuda
_v
isible
_d
evice
;
const
cuda
V
isible
D
evice
:
string
=
rmScheduleInfo
.
cuda
V
isible
D
evice
;
const
sshClient
:
Client
|
undefined
=
this
.
trialSSHClientMap
.
get
(
trialJobId
);
const
sshClient
:
Client
|
undefined
=
this
.
trialSSHClientMap
.
get
(
trialJobId
);
if
(
sshClient
===
undefined
)
{
if
(
sshClient
===
undefined
)
{
assert
(
false
,
'
sshClient is undefined.
'
);
assert
(
false
,
'
sshClient is undefined.
'
);
...
@@ -543,14 +537,14 @@ class RemoteMachineTrainingService implements TrainingService {
...
@@ -543,14 +537,14 @@ class RemoteMachineTrainingService implements TrainingService {
// See definition in remoteMachineData.ts
// See definition in remoteMachineData.ts
let
command
:
string
;
let
command
:
string
;
// Set CUDA_VISIBLE_DEVICES environment variable based on cuda
_v
isible
_d
evice
// Set CUDA_VISIBLE_DEVICES environment variable based on cuda
V
isible
D
evice
// If no valid cuda
_v
isible
_d
evice is defined, set CUDA_VISIBLE_DEVICES to empty string to hide GPU device
// If no valid cuda
V
isible
D
evice is defined, set CUDA_VISIBLE_DEVICES to empty string to hide GPU device
// If gpuNum is undefined, will not set CUDA_VISIBLE_DEVICES in script
// If gpuNum is undefined, will not set CUDA_VISIBLE_DEVICES in script
if
(
this
.
trialConfig
.
gpuNum
===
undefined
)
{
if
(
this
.
trialConfig
.
gpuNum
===
undefined
)
{
command
=
this
.
trialConfig
.
command
;
command
=
this
.
trialConfig
.
command
;
}
else
{
}
else
{
if
(
typeof
cuda
_v
isible
_d
evice
===
'
string
'
&&
cuda
_v
isible
_d
evice
.
length
>
0
)
{
if
(
typeof
cuda
V
isible
D
evice
===
'
string
'
&&
cuda
V
isible
D
evice
.
length
>
0
)
{
command
=
`CUDA_VISIBLE_DEVICES=
${
cuda
_v
isible
_d
evice
}
${
this
.
trialConfig
.
command
}
`
;
command
=
`CUDA_VISIBLE_DEVICES=
${
cuda
V
isible
D
evice
}
${
this
.
trialConfig
.
command
}
`
;
}
else
{
}
else
{
command
=
`CUDA_VISIBLE_DEVICES=" "
${
this
.
trialConfig
.
command
}
`
;
command
=
`CUDA_VISIBLE_DEVICES=" "
${
this
.
trialConfig
.
command
}
`
;
}
}
...
@@ -584,12 +578,12 @@ class RemoteMachineTrainingService implements TrainingService {
...
@@ -584,12 +578,12 @@ class RemoteMachineTrainingService implements TrainingService {
//create tmp trial working folder locally.
//create tmp trial working folder locally.
await
execCopydir
(
this
.
trialConfig
.
codeDir
,
trialLocalTempFolder
);
await
execCopydir
(
this
.
trialConfig
.
codeDir
,
trialLocalTempFolder
);
const
installScriptContent
:
string
=
CONTAINER_INSTALL_NNI_SHELL_FORMAT
;
const
installScriptContent
:
string
=
CONTAINER_INSTALL_NNI_SHELL_FORMAT
;
// Write NNI installation file to local tmp files
// Write NNI installation file to local tmp files
await
fs
.
promises
.
writeFile
(
path
.
join
(
trialLocalTempFolder
,
'
install_nni.sh
'
),
installScriptContent
,
{
encoding
:
'
utf8
'
});
await
fs
.
promises
.
writeFile
(
path
.
join
(
trialLocalTempFolder
,
'
install_nni.sh
'
),
installScriptContent
,
{
encoding
:
'
utf8
'
});
// Write file content ( run.sh and parameter.cfg ) to local tmp files
// Write file content ( run.sh and parameter.cfg ) to local tmp files
await
fs
.
promises
.
writeFile
(
path
.
join
(
trialLocalTempFolder
,
'
run.sh
'
),
runScriptTrialContent
,
{
encoding
:
'
utf8
'
});
await
fs
.
promises
.
writeFile
(
path
.
join
(
trialLocalTempFolder
,
'
run.sh
'
),
runScriptTrialContent
,
{
encoding
:
'
utf8
'
});
await
this
.
writeParameterFile
(
trialJobId
,
form
.
hyperParameters
,
rmScheduleInfo
.
rmMeta
);
await
this
.
writeParameterFile
(
trialJobId
,
form
.
hyperParameters
);
// Copy files in codeDir to remote working directory
// Copy files in codeDir to remote working directory
await
SSHClientUtility
.
copyDirectoryToRemote
(
trialLocalTempFolder
,
trialWorkingFolder
,
sshClient
,
this
.
remoteOS
);
await
SSHClientUtility
.
copyDirectoryToRemote
(
trialLocalTempFolder
,
trialWorkingFolder
,
sshClient
,
this
.
remoteOS
);
// Execute command in remote machine
// Execute command in remote machine
...
@@ -662,7 +656,7 @@ class RemoteMachineTrainingService implements TrainingService {
...
@@ -662,7 +656,7 @@ class RemoteMachineTrainingService implements TrainingService {
return
unixPathJoin
(
getRemoteTmpDir
(
this
.
remoteOS
),
'
nni
'
,
'
experiments
'
,
getExperimentId
());
return
unixPathJoin
(
getRemoteTmpDir
(
this
.
remoteOS
),
'
nni
'
,
'
experiments
'
,
getExperimentId
());
}
}
public
get
MetricsEmitter
()
:
EventEmitter
{
public
get
MetricsEmitter
():
EventEmitter
{
return
this
.
metricsEmitter
;
return
this
.
metricsEmitter
;
}
}
...
@@ -672,13 +666,10 @@ class RemoteMachineTrainingService implements TrainingService {
...
@@ -672,13 +666,10 @@ class RemoteMachineTrainingService implements TrainingService {
throw
new
NNIError
(
NNIErrorNames
.
INVALID_JOB_DETAIL
,
`Invalid job detail information for trial job
${
jobId
}
`
);
throw
new
NNIError
(
NNIErrorNames
.
INVALID_JOB_DETAIL
,
`Invalid job detail information for trial job
${
jobId
}
`
);
}
}
let
jobpidPath
:
string
;
return
unixPathJoin
(
trialJobDetail
.
workingDirectory
,
'
.nni
'
,
'
jobpid
'
);
jobpidPath
=
unixPathJoin
(
trialJobDetail
.
workingDirectory
,
'
.nni
'
,
'
jobpid
'
);
return
jobpidPath
;
}
}
private
async
writeParameterFile
(
trialJobId
:
string
,
hyperParameters
:
HyperParameters
,
rmMeta
:
RemoteMachineMeta
):
Promise
<
void
>
{
private
async
writeParameterFile
(
trialJobId
:
string
,
hyperParameters
:
HyperParameters
):
Promise
<
void
>
{
const
sshClient
:
Client
|
undefined
=
this
.
trialSSHClientMap
.
get
(
trialJobId
);
const
sshClient
:
Client
|
undefined
=
this
.
trialSSHClientMap
.
get
(
trialJobId
);
if
(
sshClient
===
undefined
)
{
if
(
sshClient
===
undefined
)
{
throw
new
Error
(
'
sshClient is undefined.
'
);
throw
new
Error
(
'
sshClient is undefined.
'
);
...
...
src/nni_manager/training_service/remote_machine/sshClientUtility.ts
View file @
1328f412
...
@@ -4,7 +4,6 @@
...
@@ -4,7 +4,6 @@
'
use strict
'
;
'
use strict
'
;
import
*
as
assert
from
'
assert
'
;
import
*
as
assert
from
'
assert
'
;
import
*
as
cpp
from
'
child-process-promise
'
;
import
*
as
os
from
'
os
'
;
import
*
as
os
from
'
os
'
;
import
*
as
path
from
'
path
'
;
import
*
as
path
from
'
path
'
;
import
{
Client
,
ClientChannel
,
SFTPWrapper
}
from
'
ssh2
'
;
import
{
Client
,
ClientChannel
,
SFTPWrapper
}
from
'
ssh2
'
;
...
@@ -22,44 +21,18 @@ import { RemoteCommandResult } from './remoteMachineData';
...
@@ -22,44 +21,18 @@ import { RemoteCommandResult } from './remoteMachineData';
*
*
*/
*/
export
namespace
SSHClientUtility
{
export
namespace
SSHClientUtility
{
/**
* Copy files and directories in local directory recursively to remote directory
* @param localDirectory local diretory
* @param remoteDirectory remote directory
* @param sshClient SSH client
*/
export
async
function
copyDirectoryToRemote
(
localDirectory
:
string
,
remoteDirectory
:
string
,
sshClient
:
Client
,
remoteOS
:
string
)
:
Promise
<
void
>
{
const
deferred
:
Deferred
<
void
>
=
new
Deferred
<
void
>
();
const
tmpTarName
:
string
=
`
${
uniqueString
(
10
)}
.tar.gz`
;
const
localTarPath
:
string
=
path
.
join
(
os
.
tmpdir
(),
tmpTarName
);
const
remoteTarPath
:
string
=
unixPathJoin
(
getRemoteTmpDir
(
remoteOS
),
tmpTarName
);
// Compress files in local directory to experiment root directory
await
tarAdd
(
localTarPath
,
localDirectory
);
// Copy the compressed file to remoteDirectory and delete it
await
copyFileToRemote
(
localTarPath
,
remoteTarPath
,
sshClient
);
await
execRemove
(
localTarPath
);
// Decompress the remote compressed file in and delete it
await
remoteExeCommand
(
`tar -oxzf
${
remoteTarPath
}
-C
${
remoteDirectory
}
`
,
sshClient
);
await
remoteExeCommand
(
`rm
${
remoteTarPath
}
`
,
sshClient
);
deferred
.
resolve
();
return
deferred
.
promise
;
}
/**
/**
* Copy local file to remote path
* Copy local file to remote path
* @param localFilePath the path of local file
* @param localFilePath the path of local file
* @param remoteFilePath the target path in remote machine
* @param remoteFilePath the target path in remote machine
* @param sshClient SSH Client
* @param sshClient SSH Client
*/
*/
export
function
copyFileToRemote
(
localFilePath
:
string
,
remoteFilePath
:
string
,
sshClient
:
Client
)
:
Promise
<
boolean
>
{
export
function
copyFileToRemote
(
localFilePath
:
string
,
remoteFilePath
:
string
,
sshClient
:
Client
):
Promise
<
boolean
>
{
const
log
:
Logger
=
getLogger
();
const
log
:
Logger
=
getLogger
();
log
.
debug
(
`copyFileToRemote: localFilePath:
${
localFilePath
}
, remoteFilePath:
${
remoteFilePath
}
`
);
log
.
debug
(
`copyFileToRemote: localFilePath:
${
localFilePath
}
, remoteFilePath:
${
remoteFilePath
}
`
);
assert
(
sshClient
!==
undefined
);
assert
(
sshClient
!==
undefined
);
const
deferred
:
Deferred
<
boolean
>
=
new
Deferred
<
boolean
>
();
const
deferred
:
Deferred
<
boolean
>
=
new
Deferred
<
boolean
>
();
sshClient
.
sftp
((
err
:
Error
,
sftp
:
SFTPWrapper
)
=>
{
sshClient
.
sftp
((
err
:
Error
,
sftp
:
SFTPWrapper
)
=>
{
if
(
err
!==
undefined
&&
err
!==
null
)
{
if
(
err
!==
undefined
&&
err
!==
null
)
{
log
.
error
(
`copyFileToRemote:
${
err
.
message
}
,
${
localFilePath
}
,
${
remoteFilePath
}
`
);
log
.
error
(
`copyFileToRemote:
${
err
.
message
}
,
${
localFilePath
}
,
${
remoteFilePath
}
`
);
deferred
.
reject
(
err
);
deferred
.
reject
(
err
);
...
@@ -67,7 +40,7 @@ export namespace SSHClientUtility {
...
@@ -67,7 +40,7 @@ export namespace SSHClientUtility {
return
;
return
;
}
}
assert
(
sftp
!==
undefined
);
assert
(
sftp
!==
undefined
);
sftp
.
fastPut
(
localFilePath
,
remoteFilePath
,
(
fastPutErr
:
Error
)
=>
{
sftp
.
fastPut
(
localFilePath
,
remoteFilePath
,
(
fastPutErr
:
Error
)
=>
{
sftp
.
end
();
sftp
.
end
();
if
(
fastPutErr
!==
undefined
&&
fastPutErr
!==
null
)
{
if
(
fastPutErr
!==
undefined
&&
fastPutErr
!==
null
)
{
deferred
.
reject
(
fastPutErr
);
deferred
.
reject
(
fastPutErr
);
...
@@ -86,15 +59,15 @@ export namespace SSHClientUtility {
...
@@ -86,15 +59,15 @@ export namespace SSHClientUtility {
* @param client SSH Client
* @param client SSH Client
*/
*/
// tslint:disable:no-unsafe-any no-any
// tslint:disable:no-unsafe-any no-any
export
function
remoteExeCommand
(
command
:
string
,
client
:
Client
):
Promise
<
RemoteCommandResult
>
{
export
function
remoteExeCommand
(
command
:
string
,
client
:
Client
):
Promise
<
RemoteCommandResult
>
{
const
log
:
Logger
=
getLogger
();
const
log
:
Logger
=
getLogger
();
log
.
debug
(
`remoteExeCommand: command: [
${
command
}
]`
);
log
.
debug
(
`remoteExeCommand: command: [
${
command
}
]`
);
const
deferred
:
Deferred
<
RemoteCommandResult
>
=
new
Deferred
<
RemoteCommandResult
>
();
const
deferred
:
Deferred
<
RemoteCommandResult
>
=
new
Deferred
<
RemoteCommandResult
>
();
let
stdout
:
string
=
''
;
let
stdout
:
string
=
''
;
let
stderr
:
string
=
''
;
let
stderr
:
string
=
''
;
let
exitCode
:
number
;
let
exitCode
:
number
;
client
.
exec
(
command
,
(
err
:
Error
,
channel
:
ClientChannel
)
=>
{
client
.
exec
(
command
,
(
err
:
Error
,
channel
:
ClientChannel
)
=>
{
if
(
err
!==
undefined
&&
err
!==
null
)
{
if
(
err
!==
undefined
&&
err
!==
null
)
{
log
.
error
(
`remoteExeCommand:
${
err
.
message
}
`
);
log
.
error
(
`remoteExeCommand:
${
err
.
message
}
`
);
deferred
.
reject
(
err
);
deferred
.
reject
(
err
);
...
@@ -102,14 +75,14 @@ export namespace SSHClientUtility {
...
@@ -102,14 +75,14 @@ export namespace SSHClientUtility {
return
;
return
;
}
}
channel
.
on
(
'
data
'
,
(
data
:
any
,
dataStderr
:
any
)
=>
{
channel
.
on
(
'
data
'
,
(
data
:
any
,
dataStderr
:
any
)
=>
{
if
(
dataStderr
!==
undefined
&&
dataStderr
!==
null
)
{
if
(
dataStderr
!==
undefined
&&
dataStderr
!==
null
)
{
stderr
+=
data
.
toString
();
stderr
+=
data
.
toString
();
}
else
{
}
else
{
stdout
+=
data
.
toString
();
stdout
+=
data
.
toString
();
}
}
})
})
.
on
(
'
exit
'
,
(
code
:
any
,
signal
:
any
)
=>
{
.
on
(
'
exit
'
,
(
code
:
any
,
signal
:
any
)
=>
{
exitCode
=
<
number
>
code
;
exitCode
=
<
number
>
code
;
deferred
.
resolve
({
deferred
.
resolve
({
stdout
:
stdout
,
stdout
:
stdout
,
...
@@ -122,9 +95,34 @@ export namespace SSHClientUtility {
...
@@ -122,9 +95,34 @@ export namespace SSHClientUtility {
return
deferred
.
promise
;
return
deferred
.
promise
;
}
}
/**
* Copy files and directories in local directory recursively to remote directory
* @param localDirectory local diretory
* @param remoteDirectory remote directory
* @param sshClient SSH client
*/
export
async
function
copyDirectoryToRemote
(
localDirectory
:
string
,
remoteDirectory
:
string
,
sshClient
:
Client
,
remoteOS
:
string
):
Promise
<
void
>
{
const
deferred
:
Deferred
<
void
>
=
new
Deferred
<
void
>
();
const
tmpTarName
:
string
=
`
${
uniqueString
(
10
)}
.tar.gz`
;
const
localTarPath
:
string
=
path
.
join
(
os
.
tmpdir
(),
tmpTarName
);
const
remoteTarPath
:
string
=
unixPathJoin
(
getRemoteTmpDir
(
remoteOS
),
tmpTarName
);
// Compress files in local directory to experiment root directory
await
tarAdd
(
localTarPath
,
localDirectory
);
// Copy the compressed file to remoteDirectory and delete it
await
copyFileToRemote
(
localTarPath
,
remoteTarPath
,
sshClient
);
await
execRemove
(
localTarPath
);
// Decompress the remote compressed file in and delete it
await
remoteExeCommand
(
`tar -oxzf
${
remoteTarPath
}
-C
${
remoteDirectory
}
`
,
sshClient
);
await
remoteExeCommand
(
`rm
${
remoteTarPath
}
`
,
sshClient
);
deferred
.
resolve
();
return
deferred
.
promise
;
}
export
function
getRemoteFileContent
(
filePath
:
string
,
sshClient
:
Client
):
Promise
<
string
>
{
export
function
getRemoteFileContent
(
filePath
:
string
,
sshClient
:
Client
):
Promise
<
string
>
{
const
deferred
:
Deferred
<
string
>
=
new
Deferred
<
string
>
();
const
deferred
:
Deferred
<
string
>
=
new
Deferred
<
string
>
();
sshClient
.
sftp
((
err
:
Error
,
sftp
:
SFTPWrapper
)
=>
{
sshClient
.
sftp
((
err
:
Error
,
sftp
:
SFTPWrapper
)
=>
{
if
(
err
!==
undefined
&&
err
!==
null
)
{
if
(
err
!==
undefined
&&
err
!==
null
)
{
getLogger
()
getLogger
()
.
error
(
`getRemoteFileContent:
${
err
.
message
}
`
);
.
error
(
`getRemoteFileContent:
${
err
.
message
}
`
);
...
@@ -133,10 +131,10 @@ export namespace SSHClientUtility {
...
@@ -133,10 +131,10 @@ export namespace SSHClientUtility {
return
;
return
;
}
}
try
{
try
{
const
sftpStream
:
stream
.
Readable
=
sftp
.
createReadStream
(
filePath
);
const
sftpStream
:
stream
.
Readable
=
sftp
.
createReadStream
(
filePath
);
let
dataBuffer
:
string
=
''
;
let
dataBuffer
:
string
=
''
;
sftpStream
.
on
(
'
data
'
,
(
data
:
Buffer
|
string
)
=>
{
sftpStream
.
on
(
'
data
'
,
(
data
:
Buffer
|
string
)
=>
{
dataBuffer
+=
data
;
dataBuffer
+=
data
;
})
})
.
on
(
'
error
'
,
(
streamErr
:
Error
)
=>
{
.
on
(
'
error
'
,
(
streamErr
:
Error
)
=>
{
...
...
Prev
1
2
3
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment