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
063d6b74
Unverified
Commit
063d6b74
authored
Apr 26, 2021
by
SparkSnail
Committed by
GitHub
Apr 26, 2021
Browse files
Merge pull request #3580 from microsoft/v2.2
[do not Squash!] Merge V2.2 back to master
parents
08986c6b
e1295888
Changes
86
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
178 additions
and
140 deletions
+178
-140
ts/nni_manager/core/nnimanager.ts
ts/nni_manager/core/nnimanager.ts
+51
-13
ts/nni_manager/rest_server/restValidationSchemas.ts
ts/nni_manager/rest_server/restValidationSchemas.ts
+5
-0
ts/nni_manager/training_service/kubernetes/frameworkcontroller/frameworkcontrollerTrainingService.ts
...frameworkcontroller/frameworkcontrollerTrainingService.ts
+5
-3
ts/nni_manager/training_service/kubernetes/kubeflow/kubeflowTrainingService.ts
...ng_service/kubernetes/kubeflow/kubeflowTrainingService.ts
+2
-1
ts/nni_manager/training_service/kubernetes/kubernetesJobRestServer.ts
...er/training_service/kubernetes/kubernetesJobRestServer.ts
+0
-1
ts/nni_manager/training_service/remote_machine/extends/linuxCommands.ts
.../training_service/remote_machine/extends/linuxCommands.ts
+4
-0
ts/nni_manager/training_service/remote_machine/extends/windowsCommands.ts
...raining_service/remote_machine/extends/windowsCommands.ts
+4
-0
ts/nni_manager/training_service/remote_machine/osCommands.ts
ts/nni_manager/training_service/remote_machine/osCommands.ts
+1
-0
ts/nni_manager/training_service/remote_machine/shellExecutor.ts
..._manager/training_service/remote_machine/shellExecutor.ts
+10
-0
ts/nni_manager/training_service/reusable/environment.ts
ts/nni_manager/training_service/reusable/environment.ts
+4
-0
ts/nni_manager/training_service/reusable/environments/amlEnvironmentService.ts
...ng_service/reusable/environments/amlEnvironmentService.ts
+16
-39
ts/nni_manager/training_service/reusable/environments/environmentServiceFactory.ts
...ervice/reusable/environments/environmentServiceFactory.ts
+1
-1
ts/nni_manager/training_service/reusable/environments/remoteEnvironmentService.ts
...service/reusable/environments/remoteEnvironmentService.ts
+16
-15
ts/nni_manager/training_service/reusable/trialDispatcher.ts
ts/nni_manager/training_service/reusable/trialDispatcher.ts
+3
-2
ts/webui/src/App.tsx
ts/webui/src/App.tsx
+1
-1
ts/webui/src/components/modals/ExperimentSummaryPanel.tsx
ts/webui/src/components/modals/ExperimentSummaryPanel.tsx
+1
-1
ts/webui/src/components/overview/count/EditExperimentParam.tsx
...bui/src/components/overview/count/EditExperimentParam.tsx
+13
-10
ts/webui/src/components/overview/count/ExpDuration.tsx
ts/webui/src/components/overview/count/ExpDuration.tsx
+1
-1
ts/webui/src/components/overview/count/TrialCount.tsx
ts/webui/src/components/overview/count/TrialCount.tsx
+1
-1
ts/webui/src/components/slideNav/TrialConfigPanel.tsx
ts/webui/src/components/slideNav/TrialConfigPanel.tsx
+39
-51
No files found.
ts/nni_manager/core/nnimanager.ts
View file @
063d6b74
...
@@ -175,12 +175,14 @@ class NNIManager implements Manager {
...
@@ -175,12 +175,14 @@ class NNIManager implements Manager {
nextSequenceId
:
0
,
nextSequenceId
:
0
,
revision
:
0
revision
:
0
};
};
this
.
config
=
config
;
this
.
log
.
info
(
`Starting experiment:
${
this
.
experimentProfile
.
id
}
`
);
this
.
log
.
info
(
`Starting experiment:
${
this
.
experimentProfile
.
id
}
`
);
await
this
.
storeExperimentProfile
();
await
this
.
storeExperimentProfile
();
this
.
log
.
info
(
'
Setup training service...
'
);
if
(
this
.
trainingService
===
undefined
)
{
this
.
trainingService
=
await
this
.
initTrainingService
(
config
);
this
.
log
.
info
(
'
Setup training service...
'
);
this
.
trainingService
=
await
this
.
initTrainingService
(
config
);
}
this
.
log
.
info
(
'
Setup tuner...
'
);
this
.
log
.
info
(
'
Setup tuner...
'
);
const
dispatcherCommand
:
string
=
getMsgDispatcherCommand
(
config
);
const
dispatcherCommand
:
string
=
getMsgDispatcherCommand
(
config
);
...
@@ -198,18 +200,22 @@ class NNIManager implements Manager {
...
@@ -198,18 +200,22 @@ class NNIManager implements Manager {
}
}
public
async
resumeExperiment
(
readonly
:
boolean
):
Promise
<
void
>
{
public
async
resumeExperiment
(
readonly
:
boolean
):
Promise
<
void
>
{
this
.
log
.
info
(
`Resuming experiment:
${
this
.
experimentProfile
.
id
}
`
);
//Fetch back the experiment profile
//Fetch back the experiment profile
const
experimentId
:
string
=
getExperimentId
();
const
experimentId
:
string
=
getExperimentId
();
this
.
log
.
info
(
`Resuming experiment:
${
experimentId
}
`
);
this
.
experimentProfile
=
await
this
.
dataStore
.
getExperimentProfile
(
experimentId
);
this
.
experimentProfile
=
await
this
.
dataStore
.
getExperimentProfile
(
experimentId
);
this
.
readonly
=
readonly
;
this
.
readonly
=
readonly
;
if
(
readonly
)
{
if
(
readonly
)
{
this
.
setStatus
(
'
VIEWED
'
);
return
Promise
.
resolve
();
return
Promise
.
resolve
();
}
}
this
.
log
.
info
(
'
Setup training service...
'
);
const
config
:
ExperimentConfig
=
this
.
experimentProfile
.
params
;
const
config
:
ExperimentConfig
=
this
.
experimentProfile
.
params
;
this
.
trainingService
=
await
this
.
initTrainingService
(
config
);
this
.
config
=
config
;
if
(
this
.
trainingService
===
undefined
)
{
this
.
log
.
info
(
'
Setup training service...
'
);
this
.
trainingService
=
await
this
.
initTrainingService
(
config
);
}
this
.
log
.
info
(
'
Setup tuner...
'
);
this
.
log
.
info
(
'
Setup tuner...
'
);
const
dispatcherCommand
:
string
=
getMsgDispatcherCommand
(
config
);
const
dispatcherCommand
:
string
=
getMsgDispatcherCommand
(
config
);
...
@@ -254,12 +260,35 @@ class NNIManager implements Manager {
...
@@ -254,12 +260,35 @@ class NNIManager implements Manager {
return
this
.
dataStore
.
getTrialJob
(
trialJobId
);
return
this
.
dataStore
.
getTrialJob
(
trialJobId
);
}
}
public
async
setClusterMetadata
(
_key
:
string
,
_value
:
string
):
Promise
<
void
>
{
public
async
setClusterMetadata
(
key
:
string
,
value
:
string
):
Promise
<
void
>
{
throw
new
Error
(
'
Calling removed API setClusterMetadata
'
);
// Hack for supporting v2 config, need refactor
if
(
this
.
trainingService
===
undefined
)
{
this
.
log
.
info
(
'
Setup training service...
'
);
switch
(
key
)
{
case
'
kubeflow_config
'
:
{
const
kubeflowModule
=
await
import
(
'
../training_service/kubernetes/kubeflow/kubeflowTrainingService
'
);
this
.
trainingService
=
new
kubeflowModule
.
KubeflowTrainingService
();
break
;
}
case
'
frameworkcontroller_config
'
:
{
const
fcModule
=
await
import
(
'
../training_service/kubernetes/frameworkcontroller/frameworkcontrollerTrainingService
'
);
this
.
trainingService
=
new
fcModule
.
FrameworkControllerTrainingService
();
break
;
}
case
'
adl_config
'
:
{
const
adlModule
=
await
import
(
'
../training_service/kubernetes/adl/adlTrainingService
'
);
this
.
trainingService
=
new
adlModule
.
AdlTrainingService
();
break
;
}
default
:
throw
new
Error
(
"
Setup training service failed.
"
);
}
}
await
this
.
trainingService
.
setClusterMetadata
(
key
,
value
);
}
}
public
getClusterMetadata
(
_
key
:
string
):
Promise
<
string
>
{
public
getClusterMetadata
(
key
:
string
):
Promise
<
string
>
{
throw
new
Error
(
'
Calling removed API
getClusterMetadata
'
);
return
this
.
trainingService
.
getClusterMetadata
(
key
);
}
}
public
async
getTrialJobStatistics
():
Promise
<
TrialJobStatistics
[]
>
{
public
async
getTrialJobStatistics
():
Promise
<
TrialJobStatistics
[]
>
{
...
@@ -404,8 +433,17 @@ class NNIManager implements Manager {
...
@@ -404,8 +433,17 @@ class NNIManager implements Manager {
}
}
private
async
initTrainingService
(
config
:
ExperimentConfig
):
Promise
<
TrainingService
>
{
private
async
initTrainingService
(
config
:
ExperimentConfig
):
Promise
<
TrainingService
>
{
this
.
config
=
config
;
let
platform
:
string
;
const
platform
=
Array
.
isArray
(
config
.
trainingService
)
?
'
hybrid
'
:
config
.
trainingService
.
platform
;
if
(
Array
.
isArray
(
config
.
trainingService
))
{
platform
=
'
hybrid
'
;
}
else
if
(
config
.
trainingService
.
platform
)
{
platform
=
config
.
trainingService
.
platform
;
}
else
{
platform
=
(
config
as
any
).
trainingServicePlatform
;
}
if
(
!
platform
)
{
throw
new
Error
(
'
Cannot detect training service platform
'
);
}
if
([
'
remote
'
,
'
pai
'
,
'
aml
'
,
'
hybrid
'
].
includes
(
platform
))
{
if
([
'
remote
'
,
'
pai
'
,
'
aml
'
,
'
hybrid
'
].
includes
(
platform
))
{
const
module_
=
await
import
(
'
../training_service/reusable/routerTrainingService
'
);
const
module_
=
await
import
(
'
../training_service/reusable/routerTrainingService
'
);
...
...
ts/nni_manager/rest_server/restValidationSchemas.ts
View file @
063d6b74
...
@@ -131,6 +131,9 @@ export namespace ValidationSchemas {
...
@@ -131,6 +131,9 @@ export namespace ValidationSchemas {
maxTrialNumPerGpu
:
joi
.
number
(),
maxTrialNumPerGpu
:
joi
.
number
(),
useActiveGpu
:
joi
.
boolean
(),
useActiveGpu
:
joi
.
boolean
(),
}),
}),
adl_config
:
joi
.
object
({
// eslint-disable-line @typescript-eslint/camelcase
// hack for v2 configuration
}),
kubeflow_config
:
joi
.
object
({
// eslint-disable-line @typescript-eslint/camelcase
kubeflow_config
:
joi
.
object
({
// eslint-disable-line @typescript-eslint/camelcase
operator
:
joi
.
string
().
min
(
1
).
required
(),
operator
:
joi
.
string
().
min
(
1
).
required
(),
storage
:
joi
.
string
().
min
(
1
),
storage
:
joi
.
string
().
min
(
1
),
...
@@ -194,6 +197,8 @@ export namespace ValidationSchemas {
...
@@ -194,6 +197,8 @@ export namespace ValidationSchemas {
nni_manager_ip
:
joi
.
object
({
// eslint-disable-line @typescript-eslint/camelcase
nni_manager_ip
:
joi
.
object
({
// eslint-disable-line @typescript-eslint/camelcase
nniManagerIp
:
joi
.
string
().
min
(
1
)
nniManagerIp
:
joi
.
string
().
min
(
1
)
}),
}),
version_check
:
joi
.
boolean
(),
// eslint-disable-line @typescript-eslint/camelcase
log_collection
:
joi
.
string
(),
// eslint-disable-line @typescript-eslint/camelcase
remote_config
:
joi
.
object
({
// eslint-disable-line @typescript-eslint/camelcase
remote_config
:
joi
.
object
({
// eslint-disable-line @typescript-eslint/camelcase
reuse
:
joi
.
boolean
()
reuse
:
joi
.
boolean
()
}),
}),
...
...
ts/nni_manager/training_service/kubernetes/frameworkcontroller/frameworkcontrollerTrainingService.ts
View file @
063d6b74
...
@@ -19,6 +19,7 @@ import {validateCodeDir} from '../../common/util';
...
@@ -19,6 +19,7 @@ import {validateCodeDir} from '../../common/util';
import
{
NFSConfig
}
from
'
../kubernetesConfig
'
;
import
{
NFSConfig
}
from
'
../kubernetesConfig
'
;
import
{
KubernetesTrialJobDetail
}
from
'
../kubernetesData
'
;
import
{
KubernetesTrialJobDetail
}
from
'
../kubernetesData
'
;
import
{
KubernetesTrainingService
}
from
'
../kubernetesTrainingService
'
;
import
{
KubernetesTrainingService
}
from
'
../kubernetesTrainingService
'
;
import
{
KubernetesJobRestServer
}
from
'
../kubernetesJobRestServer
'
;
import
{
FrameworkControllerClientFactory
}
from
'
./frameworkcontrollerApiClient
'
;
import
{
FrameworkControllerClientFactory
}
from
'
./frameworkcontrollerApiClient
'
;
import
{
import
{
FrameworkControllerClusterConfig
,
FrameworkControllerClusterConfig
,
...
@@ -52,7 +53,7 @@ class FrameworkControllerTrainingService extends KubernetesTrainingService imple
...
@@ -52,7 +53,7 @@ class FrameworkControllerTrainingService extends KubernetesTrainingService imple
}
}
public
async
run
():
Promise
<
void
>
{
public
async
run
():
Promise
<
void
>
{
this
.
kubernetesJobRestServer
=
component
.
get
(
FrameworkController
JobRestServer
);
this
.
kubernetesJobRestServer
=
new
Kubernetes
JobRestServer
(
this
);
if
(
this
.
kubernetesJobRestServer
===
undefined
)
{
if
(
this
.
kubernetesJobRestServer
===
undefined
)
{
throw
new
Error
(
'
kubernetesJobRestServer not initialized!
'
);
throw
new
Error
(
'
kubernetesJobRestServer not initialized!
'
);
}
}
...
@@ -140,10 +141,11 @@ class FrameworkControllerTrainingService extends KubernetesTrainingService imple
...
@@ -140,10 +141,11 @@ class FrameworkControllerTrainingService extends KubernetesTrainingService imple
const
trialLocalTempFolder
:
string
=
path
.
join
(
getExperimentRootDir
(),
'
trials-local
'
,
trialJobId
);
const
trialLocalTempFolder
:
string
=
path
.
join
(
getExperimentRootDir
(),
'
trials-local
'
,
trialJobId
);
let
frameworkcontrollerJobName
:
string
=
`nniexp
${
this
.
experimentId
}
trial
${
trialJobId
}
`
.
toLowerCase
();
let
frameworkcontrollerJobName
:
string
=
`nniexp
${
this
.
experimentId
}
trial
${
trialJobId
}
`
.
toLowerCase
();
// Create frameworkcontroller job based on generated frameworkcontroller job resource config
let
frameworkcontrollerJobConfig
:
any
;
let
frameworkcontrollerJobConfig
=
JSON
.
parse
(
JSON
.
stringify
(
this
.
fcTemplate
));
if
(
this
.
fcTemplate
!==
undefined
)
{
if
(
this
.
fcTemplate
!==
undefined
)
{
// Create frameworkcontroller job based on generated frameworkcontroller job resource config
frameworkcontrollerJobConfig
=
JSON
.
parse
(
JSON
.
stringify
(
this
.
fcTemplate
));
// add a custom name extension to the job name and apply it to the custom template
// add a custom name extension to the job name and apply it to the custom template
frameworkcontrollerJobName
+=
"
xx
"
+
this
.
fcTemplate
.
metadata
.
name
;
frameworkcontrollerJobName
+=
"
xx
"
+
this
.
fcTemplate
.
metadata
.
name
;
// Process custom task roles commands
// Process custom task roles commands
...
...
ts/nni_manager/training_service/kubernetes/kubeflow/kubeflowTrainingService.ts
View file @
063d6b74
...
@@ -19,6 +19,7 @@ import { TrialConfigMetadataKey } from '../../common/trialConfigMetadataKey';
...
@@ -19,6 +19,7 @@ import { TrialConfigMetadataKey } from '../../common/trialConfigMetadataKey';
import
{
validateCodeDir
}
from
'
../../common/util
'
;
import
{
validateCodeDir
}
from
'
../../common/util
'
;
import
{
NFSConfig
}
from
'
../kubernetesConfig
'
;
import
{
NFSConfig
}
from
'
../kubernetesConfig
'
;
import
{
KubernetesTrialJobDetail
}
from
'
../kubernetesData
'
;
import
{
KubernetesTrialJobDetail
}
from
'
../kubernetesData
'
;
import
{
KubernetesJobRestServer
}
from
'
../kubernetesJobRestServer
'
;
import
{
KubernetesTrainingService
}
from
'
../kubernetesTrainingService
'
;
import
{
KubernetesTrainingService
}
from
'
../kubernetesTrainingService
'
;
import
{
KubeflowOperatorClientFactory
}
from
'
./kubeflowApiClient
'
;
import
{
KubeflowOperatorClientFactory
}
from
'
./kubeflowApiClient
'
;
import
{
KubeflowClusterConfig
,
KubeflowClusterConfigAzure
,
KubeflowClusterConfigFactory
,
KubeflowClusterConfigNFS
,
import
{
KubeflowClusterConfig
,
KubeflowClusterConfigAzure
,
KubeflowClusterConfigFactory
,
KubeflowClusterConfigNFS
,
...
@@ -46,7 +47,7 @@ class KubeflowTrainingService extends KubernetesTrainingService implements Kuber
...
@@ -46,7 +47,7 @@ class KubeflowTrainingService extends KubernetesTrainingService implements Kuber
public
async
run
():
Promise
<
void
>
{
public
async
run
():
Promise
<
void
>
{
this
.
log
.
info
(
'
Run Kubeflow training service.
'
);
this
.
log
.
info
(
'
Run Kubeflow training service.
'
);
this
.
kubernetesJobRestServer
=
component
.
get
(
Kubeflow
JobRestServer
);
this
.
kubernetesJobRestServer
=
new
Kubernetes
JobRestServer
(
this
);
if
(
this
.
kubernetesJobRestServer
===
undefined
)
{
if
(
this
.
kubernetesJobRestServer
===
undefined
)
{
throw
new
Error
(
'
kubernetesJobRestServer not initialized!
'
);
throw
new
Error
(
'
kubernetesJobRestServer not initialized!
'
);
}
}
...
...
ts/nni_manager/training_service/kubernetes/kubernetesJobRestServer.ts
View file @
063d6b74
...
@@ -16,7 +16,6 @@ import { KubernetesTrainingService } from './kubernetesTrainingService';
...
@@ -16,7 +16,6 @@ import { KubernetesTrainingService } from './kubernetesTrainingService';
export
class
KubernetesJobRestServer
extends
ClusterJobRestServer
{
export
class
KubernetesJobRestServer
extends
ClusterJobRestServer
{
@
Inject
@
Inject
private
readonly
kubernetesTrainingService
?
:
KubernetesTrainingService
;
private
readonly
kubernetesTrainingService
?
:
KubernetesTrainingService
;
/**
/**
* constructor to provide NNIRestServer's own rest property, e.g. port
* constructor to provide NNIRestServer's own rest property, e.g. port
*/
*/
...
...
ts/nni_manager/training_service/remote_machine/extends/linuxCommands.ts
View file @
063d6b74
...
@@ -146,6 +146,10 @@ class LinuxCommands extends OsCommands {
...
@@ -146,6 +146,10 @@ class LinuxCommands extends OsCommands {
public
fileExistCommand
(
filePath
:
string
):
string
{
public
fileExistCommand
(
filePath
:
string
):
string
{
return
`test -e
${
filePath
}
&& echo True || echo False`
;
return
`test -e
${
filePath
}
&& echo True || echo False`
;
}
}
public
getCurrentPath
():
string
{
return
`pwd`
;
}
}
}
export
{
LinuxCommands
};
export
{
LinuxCommands
};
ts/nni_manager/training_service/remote_machine/extends/windowsCommands.ts
View file @
063d6b74
...
@@ -134,6 +134,10 @@ class WindowsCommands extends OsCommands {
...
@@ -134,6 +134,10 @@ class WindowsCommands extends OsCommands {
public
fileExistCommand
(
filePath
:
string
):
string
{
public
fileExistCommand
(
filePath
:
string
):
string
{
return
`powershell Test-Path
${
filePath
}
-PathType Leaf`
;
return
`powershell Test-Path
${
filePath
}
-PathType Leaf`
;
}
}
public
getCurrentPath
():
string
{
return
`chdir`
;
}
}
}
export
{
WindowsCommands
};
export
{
WindowsCommands
};
ts/nni_manager/training_service/remote_machine/osCommands.ts
View file @
063d6b74
...
@@ -30,6 +30,7 @@ abstract class OsCommands {
...
@@ -30,6 +30,7 @@ abstract class OsCommands {
public
abstract
executeScript
(
script
:
string
,
isFile
:
boolean
):
string
;
public
abstract
executeScript
(
script
:
string
,
isFile
:
boolean
):
string
;
public
abstract
setPythonPath
(
pythonPath
:
string
|
undefined
,
command
:
string
|
undefined
):
string
|
undefined
;
public
abstract
setPythonPath
(
pythonPath
:
string
|
undefined
,
command
:
string
|
undefined
):
string
|
undefined
;
public
abstract
fileExistCommand
(
filePath
:
string
):
string
|
undefined
;
public
abstract
fileExistCommand
(
filePath
:
string
):
string
|
undefined
;
public
abstract
getCurrentPath
():
string
;
public
joinPath
(...
paths
:
string
[]):
string
{
public
joinPath
(...
paths
:
string
[]):
string
{
let
dir
:
string
=
paths
.
filter
((
path
:
any
)
=>
path
!==
''
).
join
(
this
.
pathSpliter
);
let
dir
:
string
=
paths
.
filter
((
path
:
any
)
=>
path
!==
''
).
join
(
this
.
pathSpliter
);
...
...
ts/nni_manager/training_service/remote_machine/shellExecutor.ts
View file @
063d6b74
...
@@ -169,6 +169,16 @@ class ShellExecutor {
...
@@ -169,6 +169,16 @@ class ShellExecutor {
return
this
.
tempPath
;
return
this
.
tempPath
;
}
}
public
async
getCurrentPath
():
Promise
<
string
>
{
const
commandText
=
this
.
osCommands
&&
this
.
osCommands
.
getCurrentPath
();
const
commandResult
=
await
this
.
execute
(
commandText
);
if
(
commandResult
.
exitCode
==
0
)
{
return
commandResult
.
stdout
;
}
else
{
throw
Error
(
commandResult
.
stderr
);
}
}
public
getRemoteScriptsPath
(
experimentId
:
string
):
string
{
public
getRemoteScriptsPath
(
experimentId
:
string
):
string
{
return
this
.
joinPath
(
this
.
getRemoteExperimentRootDir
(
experimentId
),
'
scripts
'
);
return
this
.
joinPath
(
this
.
getRemoteExperimentRootDir
(
experimentId
),
'
scripts
'
);
}
}
...
...
ts/nni_manager/training_service/reusable/environment.ts
View file @
063d6b74
...
@@ -128,6 +128,10 @@ export class EnvironmentInformation {
...
@@ -128,6 +128,10 @@ export class EnvironmentInformation {
export
abstract
class
EnvironmentService
{
export
abstract
class
EnvironmentService
{
public
async
init
():
Promise
<
void
>
{
return
;
}
public
abstract
get
hasStorageService
():
boolean
;
public
abstract
get
hasStorageService
():
boolean
;
public
abstract
refreshEnvironmentsStatus
(
environments
:
EnvironmentInformation
[]):
Promise
<
void
>
;
public
abstract
refreshEnvironmentsStatus
(
environments
:
EnvironmentInformation
[]):
Promise
<
void
>
;
public
abstract
stopEnvironment
(
environment
:
EnvironmentInformation
):
Promise
<
void
>
;
public
abstract
stopEnvironment
(
environment
:
EnvironmentInformation
):
Promise
<
void
>
;
...
...
ts/nni_manager/training_service/reusable/environments/amlEnvironmentService.ts
View file @
063d6b74
...
@@ -9,15 +9,16 @@ import * as component from '../../../common/component';
...
@@ -9,15 +9,16 @@ import * as component from '../../../common/component';
import
{
getExperimentId
}
from
'
../../../common/experimentStartupInfo
'
;
import
{
getExperimentId
}
from
'
../../../common/experimentStartupInfo
'
;
import
{
getLogger
,
Logger
}
from
'
../../../common/log
'
;
import
{
getLogger
,
Logger
}
from
'
../../../common/log
'
;
import
{
getExperimentRootDir
}
from
'
../../../common/utils
'
;
import
{
getExperimentRootDir
}
from
'
../../../common/utils
'
;
import
{
TrialConfigMetadataKey
}
from
'
../../common/
trialConfigMetadataKey
'
;
import
{
ExperimentConfig
,
AmlConfig
,
flattenConfig
}
from
'
../../
../
common/
experimentConfig
'
;
import
{
validateCodeDir
}
from
'
../../common/util
'
;
import
{
validateCodeDir
}
from
'
../../common/util
'
;
import
{
AMLClient
}
from
'
../aml/amlClient
'
;
import
{
AMLClient
}
from
'
../aml/amlClient
'
;
import
{
AMLClusterConfig
,
AMLEnvironmentInformation
,
AMLTrialConfig
}
from
'
../aml/amlConfig
'
;
import
{
AMLEnvironmentInformation
}
from
'
../aml/amlConfig
'
;
import
{
EnvironmentInformation
,
EnvironmentService
}
from
'
../environment
'
;
import
{
EnvironmentInformation
,
EnvironmentService
}
from
'
../environment
'
;
import
{
EventEmitter
}
from
"
events
"
;
import
{
EventEmitter
}
from
"
events
"
;
import
{
AMLCommandChannel
}
from
'
../channels/amlCommandChannel
'
;
import
{
AMLCommandChannel
}
from
'
../channels/amlCommandChannel
'
;
import
{
SharedStorageService
}
from
'
../sharedStorage
'
import
{
SharedStorageService
}
from
'
../sharedStorage
'
interface
FlattenAmlConfig
extends
ExperimentConfig
,
AmlConfig
{
}
/**
/**
* Collector AML jobs info from AML cluster, and update aml job status locally
* Collector AML jobs info from AML cluster, and update aml job status locally
...
@@ -26,15 +27,16 @@ import { SharedStorageService } from '../sharedStorage'
...
@@ -26,15 +27,16 @@ import { SharedStorageService } from '../sharedStorage'
export
class
AMLEnvironmentService
extends
EnvironmentService
{
export
class
AMLEnvironmentService
extends
EnvironmentService
{
private
readonly
log
:
Logger
=
getLogger
();
private
readonly
log
:
Logger
=
getLogger
();
public
amlClusterConfig
:
AMLClusterConfig
|
undefined
;
public
amlTrialConfig
:
AMLTrialConfig
|
undefined
;
private
experimentId
:
string
;
private
experimentId
:
string
;
private
experimentRootDir
:
string
;
private
experimentRootDir
:
string
;
private
config
:
FlattenAmlConfig
;
constructor
()
{
constructor
(
config
:
ExperimentConfig
)
{
super
();
super
();
this
.
experimentId
=
getExperimentId
();
this
.
experimentId
=
getExperimentId
();
this
.
experimentRootDir
=
getExperimentRootDir
();
this
.
experimentRootDir
=
getExperimentRootDir
();
this
.
config
=
flattenConfig
(
config
,
'
aml
'
);
validateCodeDir
(
this
.
config
.
trialCodeDirectory
);
}
}
public
get
hasStorageService
():
boolean
{
public
get
hasStorageService
():
boolean
{
...
@@ -53,27 +55,6 @@ export class AMLEnvironmentService extends EnvironmentService {
...
@@ -53,27 +55,6 @@ export class AMLEnvironmentService extends EnvironmentService {
return
'
aml
'
;
return
'
aml
'
;
}
}
public
async
config
(
key
:
string
,
value
:
string
):
Promise
<
void
>
{
switch
(
key
)
{
case
TrialConfigMetadataKey
.
AML_CLUSTER_CONFIG
:
this
.
amlClusterConfig
=
<
AMLClusterConfig
>
JSON
.
parse
(
value
);
break
;
case
TrialConfigMetadataKey
.
TRIAL_CONFIG
:
{
if
(
this
.
amlClusterConfig
===
undefined
)
{
this
.
log
.
error
(
'
aml cluster config is not initialized
'
);
break
;
}
this
.
amlTrialConfig
=
<
AMLTrialConfig
>
JSON
.
parse
(
value
);
// Validate to make sure codeDir doesn't have too many files
await
validateCodeDir
(
this
.
amlTrialConfig
.
codeDir
);
break
;
}
default
:
this
.
log
.
debug
(
`AML not proccessed metadata key: '
${
key
}
', value: '
${
value
}
'`
);
}
}
public
async
refreshEnvironmentsStatus
(
environments
:
EnvironmentInformation
[]):
Promise
<
void
>
{
public
async
refreshEnvironmentsStatus
(
environments
:
EnvironmentInformation
[]):
Promise
<
void
>
{
environments
.
forEach
(
async
(
environment
)
=>
{
environments
.
forEach
(
async
(
environment
)
=>
{
const
amlClient
=
(
environment
as
AMLEnvironmentInformation
).
amlClient
;
const
amlClient
=
(
environment
as
AMLEnvironmentInformation
).
amlClient
;
...
@@ -107,12 +88,6 @@ export class AMLEnvironmentService extends EnvironmentService {
...
@@ -107,12 +88,6 @@ export class AMLEnvironmentService extends EnvironmentService {
}
}
public
async
startEnvironment
(
environment
:
EnvironmentInformation
):
Promise
<
void
>
{
public
async
startEnvironment
(
environment
:
EnvironmentInformation
):
Promise
<
void
>
{
if
(
this
.
amlClusterConfig
===
undefined
)
{
throw
new
Error
(
'
AML Cluster config is not initialized
'
);
}
if
(
this
.
amlTrialConfig
===
undefined
)
{
throw
new
Error
(
'
AML trial config is not initialized
'
);
}
const
amlEnvironment
:
AMLEnvironmentInformation
=
environment
as
AMLEnvironmentInformation
;
const
amlEnvironment
:
AMLEnvironmentInformation
=
environment
as
AMLEnvironmentInformation
;
const
environmentLocalTempFolder
=
path
.
join
(
this
.
experimentRootDir
,
"
environment-temp
"
);
const
environmentLocalTempFolder
=
path
.
join
(
this
.
experimentRootDir
,
"
environment-temp
"
);
if
(
!
fs
.
existsSync
(
environmentLocalTempFolder
))
{
if
(
!
fs
.
existsSync
(
environmentLocalTempFolder
))
{
...
@@ -126,22 +101,24 @@ export class AMLEnvironmentService extends EnvironmentService {
...
@@ -126,22 +101,24 @@ export class AMLEnvironmentService extends EnvironmentService {
amlEnvironment
.
command
=
`mv envs outputs/envs && cd outputs &&
${
amlEnvironment
.
command
}
`
;
amlEnvironment
.
command
=
`mv envs outputs/envs && cd outputs &&
${
amlEnvironment
.
command
}
`
;
}
}
amlEnvironment
.
command
=
`import os\nos.system('
${
amlEnvironment
.
command
}
')`
;
amlEnvironment
.
command
=
`import os\nos.system('
${
amlEnvironment
.
command
}
')`
;
amlEnvironment
.
useActiveGpu
=
this
.
amlClusterConfig
.
useActiveGpu
;
amlEnvironment
.
useActiveGpu
=
!!
this
.
config
.
deprecated
.
useActiveGpu
;
amlEnvironment
.
maxTrialNumberPerGpu
=
this
.
amlClusterC
onfig
.
maxTrialNumPerGpu
;
amlEnvironment
.
maxTrialNumberPerGpu
=
this
.
c
onfig
.
maxTrialNum
ber
PerGpu
;
await
fs
.
promises
.
writeFile
(
path
.
join
(
environmentLocalTempFolder
,
'
nni_script.py
'
),
amlEnvironment
.
command
,
{
encoding
:
'
utf8
'
});
await
fs
.
promises
.
writeFile
(
path
.
join
(
environmentLocalTempFolder
,
'
nni_script.py
'
),
amlEnvironment
.
command
,
{
encoding
:
'
utf8
'
});
const
amlClient
=
new
AMLClient
(
const
amlClient
=
new
AMLClient
(
this
.
amlClusterC
onfig
.
subscriptionId
,
this
.
c
onfig
.
subscriptionId
,
this
.
amlClusterC
onfig
.
resourceGroup
,
this
.
c
onfig
.
resourceGroup
,
this
.
amlClusterC
onfig
.
workspaceName
,
this
.
c
onfig
.
workspaceName
,
this
.
experimentId
,
this
.
experimentId
,
this
.
amlClusterC
onfig
.
computeTarget
,
this
.
c
onfig
.
computeTarget
,
this
.
amlTrialConfig
.
i
mage
,
this
.
config
.
dockerI
mage
,
'
nni_script.py
'
,
'
nni_script.py
'
,
environmentLocalTempFolder
environmentLocalTempFolder
);
);
amlEnvironment
.
id
=
await
amlClient
.
submit
();
amlEnvironment
.
id
=
await
amlClient
.
submit
();
this
.
log
.
debug
(
'
aml: before getTrackingUrl
'
);
amlEnvironment
.
trackingUrl
=
await
amlClient
.
getTrackingUrl
();
amlEnvironment
.
trackingUrl
=
await
amlClient
.
getTrackingUrl
();
this
.
log
.
debug
(
'
aml: after getTrackingUrl
'
);
amlEnvironment
.
amlClient
=
amlClient
;
amlEnvironment
.
amlClient
=
amlClient
;
}
}
...
...
ts/nni_manager/training_service/reusable/environments/environmentServiceFactory.ts
View file @
063d6b74
...
@@ -13,7 +13,7 @@ export class EnvironmentServiceFactory {
...
@@ -13,7 +13,7 @@ export class EnvironmentServiceFactory {
case
'
remote
'
:
case
'
remote
'
:
return
new
RemoteEnvironmentService
(
config
);
return
new
RemoteEnvironmentService
(
config
);
case
'
aml
'
:
case
'
aml
'
:
return
new
AMLEnvironmentService
();
return
new
AMLEnvironmentService
(
config
);
case
'
openpai
'
:
case
'
openpai
'
:
return
new
OpenPaiEnvironmentService
(
config
);
return
new
OpenPaiEnvironmentService
(
config
);
default
:
default
:
...
...
ts/nni_manager/training_service/reusable/environments/remoteEnvironmentService.ts
View file @
063d6b74
...
@@ -27,7 +27,7 @@ export class RemoteEnvironmentService extends EnvironmentService {
...
@@ -27,7 +27,7 @@ export class RemoteEnvironmentService extends EnvironmentService {
private
readonly
environmentExecutorManagerMap
:
Map
<
string
,
ExecutorManager
>
;
private
readonly
environmentExecutorManagerMap
:
Map
<
string
,
ExecutorManager
>
;
private
readonly
remoteMachineMetaOccupiedMap
:
Map
<
RemoteMachineConfig
,
boolean
>
;
private
readonly
remoteMachineMetaOccupiedMap
:
Map
<
RemoteMachineConfig
,
boolean
>
;
private
readonly
log
:
Logger
;
private
readonly
log
:
Logger
;
private
sshConnectionPromises
:
any
[];
private
sshConnectionPromises
:
Promise
<
void
[]
>
;
private
experimentRootDir
:
string
;
private
experimentRootDir
:
string
;
private
remoteExperimentRootDir
:
string
=
""
;
private
remoteExperimentRootDir
:
string
=
""
;
private
experimentId
:
string
;
private
experimentId
:
string
;
...
@@ -39,7 +39,6 @@ export class RemoteEnvironmentService extends EnvironmentService {
...
@@ -39,7 +39,6 @@ export class RemoteEnvironmentService extends EnvironmentService {
this
.
environmentExecutorManagerMap
=
new
Map
<
string
,
ExecutorManager
>
();
this
.
environmentExecutorManagerMap
=
new
Map
<
string
,
ExecutorManager
>
();
this
.
machineExecutorManagerMap
=
new
Map
<
RemoteMachineConfig
,
ExecutorManager
>
();
this
.
machineExecutorManagerMap
=
new
Map
<
RemoteMachineConfig
,
ExecutorManager
>
();
this
.
remoteMachineMetaOccupiedMap
=
new
Map
<
RemoteMachineConfig
,
boolean
>
();
this
.
remoteMachineMetaOccupiedMap
=
new
Map
<
RemoteMachineConfig
,
boolean
>
();
this
.
sshConnectionPromises
=
[];
this
.
experimentRootDir
=
getExperimentRootDir
();
this
.
experimentRootDir
=
getExperimentRootDir
();
this
.
experimentId
=
getExperimentId
();
this
.
experimentId
=
getExperimentId
();
this
.
log
=
getLogger
();
this
.
log
=
getLogger
();
...
@@ -50,9 +49,18 @@ export class RemoteEnvironmentService extends EnvironmentService {
...
@@ -50,9 +49,18 @@ export class RemoteEnvironmentService extends EnvironmentService {
throw
new
Error
(
`codeDir
${
this
.
config
.
trialCodeDirectory
}
is not a directory`
);
throw
new
Error
(
`codeDir
${
this
.
config
.
trialCodeDirectory
}
is not a directory`
);
}
}
this
.
sshConnectionPromises
=
this
.
config
.
machineList
.
map
(
this
.
sshConnectionPromises
=
Promise
.
all
(
this
.
config
.
machineList
.
map
(
machine
=>
this
.
initRemoteMachineOnConnected
(
machine
)
machine
=>
this
.
initRemoteMachineOnConnected
(
machine
)
);
));
}
public
async
init
():
Promise
<
void
>
{
await
this
.
sshConnectionPromises
;
this
.
log
.
info
(
'
ssh connection initialized!
'
);
Array
.
from
(
this
.
machineExecutorManagerMap
.
keys
()).
forEach
(
rmMeta
=>
{
// initialize remoteMachineMetaOccupiedMap, false means not occupied
this
.
remoteMachineMetaOccupiedMap
.
set
(
rmMeta
,
false
);
});
}
}
public
get
prefetchedEnvironmentCount
():
number
{
public
get
prefetchedEnvironmentCount
():
number
{
...
@@ -204,16 +212,6 @@ export class RemoteEnvironmentService extends EnvironmentService {
...
@@ -204,16 +212,6 @@ export class RemoteEnvironmentService extends EnvironmentService {
}
}
public
async
startEnvironment
(
environment
:
EnvironmentInformation
):
Promise
<
void
>
{
public
async
startEnvironment
(
environment
:
EnvironmentInformation
):
Promise
<
void
>
{
if
(
this
.
sshConnectionPromises
.
length
>
0
)
{
await
Promise
.
all
(
this
.
sshConnectionPromises
);
this
.
log
.
info
(
'
ssh connection initialized!
'
);
// set sshConnectionPromises to [] to avoid log information duplicated
this
.
sshConnectionPromises
=
[];
Array
.
from
(
this
.
machineExecutorManagerMap
.
keys
()).
forEach
(
rmMeta
=>
{
// initialize remoteMachineMetaOccupiedMap, false means not occupied
this
.
remoteMachineMetaOccupiedMap
.
set
(
rmMeta
,
false
);
});
}
const
remoteEnvironment
:
RemoteMachineEnvironmentInformation
=
environment
as
RemoteMachineEnvironmentInformation
;
const
remoteEnvironment
:
RemoteMachineEnvironmentInformation
=
environment
as
RemoteMachineEnvironmentInformation
;
remoteEnvironment
.
status
=
'
WAITING
'
;
remoteEnvironment
.
status
=
'
WAITING
'
;
// schedule machine for environment, generate command
// schedule machine for environment, generate command
...
@@ -238,7 +236,10 @@ export class RemoteEnvironmentService extends EnvironmentService {
...
@@ -238,7 +236,10 @@ export class RemoteEnvironmentService extends EnvironmentService {
const
executor
=
await
this
.
getExecutor
(
environment
.
id
);
const
executor
=
await
this
.
getExecutor
(
environment
.
id
);
if
(
environment
.
useSharedStorage
)
{
if
(
environment
.
useSharedStorage
)
{
this
.
remoteExperimentRootDir
=
component
.
get
<
SharedStorageService
>
(
SharedStorageService
).
remoteWorkingRoot
;
this
.
remoteExperimentRootDir
=
component
.
get
<
SharedStorageService
>
(
SharedStorageService
).
remoteWorkingRoot
;
const
remoteMountCommand
=
component
.
get
<
SharedStorageService
>
(
SharedStorageService
).
remoteMountCommand
.
replace
(
/echo -e /g
,
`echo `
).
replace
(
/echo /g
,
`echo -e `
);
if
(
!
this
.
remoteExperimentRootDir
.
startsWith
(
'
/
'
))
{
this
.
remoteExperimentRootDir
=
executor
.
joinPath
((
await
executor
.
getCurrentPath
()).
trim
(),
this
.
remoteExperimentRootDir
);
}
const
remoteMountCommand
=
component
.
get
<
SharedStorageService
>
(
SharedStorageService
).
remoteMountCommand
.
replace
(
/echo -e /g
,
`echo `
).
replace
(
/echo /g
,
`echo -e `
).
replace
(
/
\\\$
/g
,
`\\\\\
\$
`
);
const
result
=
await
executor
.
executeScript
(
remoteMountCommand
,
false
,
false
);
const
result
=
await
executor
.
executeScript
(
remoteMountCommand
,
false
,
false
);
if
(
result
.
exitCode
!==
0
)
{
if
(
result
.
exitCode
!==
0
)
{
throw
new
Error
(
`Mount shared storage on remote machine failed.\n ERROR:
${
result
.
stderr
}
`
);
throw
new
Error
(
`Mount shared storage on remote machine failed.\n ERROR:
${
result
.
stderr
}
`
);
...
...
ts/nni_manager/training_service/reusable/trialDispatcher.ts
View file @
063d6b74
...
@@ -122,7 +122,6 @@ class TrialDispatcher implements TrainingService {
...
@@ -122,7 +122,6 @@ class TrialDispatcher implements TrainingService {
this
.
environmentServiceList
.
push
(
env
);
this
.
environmentServiceList
.
push
(
env
);
}
}
// FIXME: max?
this
.
environmentMaintenceLoopInterval
=
Math
.
max
(
this
.
environmentMaintenceLoopInterval
=
Math
.
max
(
...
this
.
environmentServiceList
.
map
((
env
)
=>
env
.
environmentMaintenceLoopInterval
)
...
this
.
environmentServiceList
.
map
((
env
)
=>
env
.
environmentMaintenceLoopInterval
)
);
);
...
@@ -211,6 +210,7 @@ class TrialDispatcher implements TrainingService {
...
@@ -211,6 +210,7 @@ class TrialDispatcher implements TrainingService {
}
}
public
async
run
():
Promise
<
void
>
{
public
async
run
():
Promise
<
void
>
{
await
Promise
.
all
(
this
.
environmentServiceList
.
map
(
env
=>
env
.
init
()));
for
(
const
environmentService
of
this
.
environmentServiceList
)
{
for
(
const
environmentService
of
this
.
environmentServiceList
)
{
const
runnerSettings
:
RunnerSettings
=
new
RunnerSettings
();
const
runnerSettings
:
RunnerSettings
=
new
RunnerSettings
();
...
@@ -497,9 +497,10 @@ class TrialDispatcher implements TrainingService {
...
@@ -497,9 +497,10 @@ class TrialDispatcher implements TrainingService {
liveEnvironmentsCount
++
;
liveEnvironmentsCount
++
;
if
(
environment
.
status
===
"
RUNNING
"
&&
environment
.
isRunnerReady
)
{
if
(
environment
.
status
===
"
RUNNING
"
&&
environment
.
isRunnerReady
)
{
// if environment is not reusable and used, stop and not count as idle;
// if environment is not reusable and used, stop and not count as idle;
const
reuseMode
=
Array
.
isArray
(
this
.
config
.
trainingService
)
||
(
this
.
config
.
trainingService
as
any
).
reuseMode
;
if
(
if
(
0
===
environment
.
runningTrialCount
&&
0
===
environment
.
runningTrialCount
&&
!
(
this
.
config
as
any
).
reuseMod
e
&&
reuseMode
===
fals
e
&&
environment
.
assignedTrialCount
>
0
environment
.
assignedTrialCount
>
0
)
{
)
{
if
(
environment
.
environmentService
===
undefined
)
{
if
(
environment
.
environmentService
===
undefined
)
{
...
...
ts/webui/src/App.tsx
View file @
063d6b74
...
@@ -237,7 +237,7 @@ class App extends React.Component<{}, AppState> {
...
@@ -237,7 +237,7 @@ class App extends React.Component<{}, AppState> {
}
}
// experiment status and /trial-jobs api's status could decide website update
// experiment status and /trial-jobs api's status could decide website update
if
([
'
DONE
'
,
'
ERROR
'
,
'
STOPPED
'
].
includes
(
EXPERIMENT
.
status
)
||
TRIALS
.
jobListError
())
{
if
([
'
DONE
'
,
'
ERROR
'
,
'
STOPPED
'
,
'
VIEWED
'
].
includes
(
EXPERIMENT
.
status
)
||
TRIALS
.
jobListError
())
{
// experiment finished, refresh once more to ensure consistency
// experiment finished, refresh once more to ensure consistency
this
.
setState
(()
=>
({
interval
:
0
,
isUpdate
:
false
}));
this
.
setState
(()
=>
({
interval
:
0
,
isUpdate
:
false
}));
return
;
return
;
...
...
ts/webui/src/components/modals/ExperimentSummaryPanel.tsx
View file @
063d6b74
...
@@ -54,7 +54,7 @@ class ExperimentSummaryPanel extends React.Component<ExpDrawerProps, ExpDrawerSt
...
@@ -54,7 +54,7 @@ class ExperimentSummaryPanel extends React.Component<ExpDrawerProps, ExpDrawerSt
this
.
setState
({
experiment
:
JSON
.
stringify
(
result
,
null
,
4
)
});
this
.
setState
({
experiment
:
JSON
.
stringify
(
result
,
null
,
4
)
});
}
}
if
([
'
DONE
'
,
'
ERROR
'
,
'
STOPPED
'
].
includes
(
EXPERIMENT
.
status
))
{
if
([
'
DONE
'
,
'
ERROR
'
,
'
STOPPED
'
,
'
VIEWED
'
].
includes
(
EXPERIMENT
.
status
))
{
if
(
this
.
refreshId
!==
null
||
this
.
refreshId
!==
undefined
)
{
if
(
this
.
refreshId
!==
null
||
this
.
refreshId
!==
undefined
)
{
window
.
clearInterval
(
this
.
refreshId
);
window
.
clearInterval
(
this
.
refreshId
);
}
}
...
...
ts/webui/src/components/overview/count/EditExperimentParam.tsx
View file @
063d6b74
...
@@ -30,6 +30,7 @@ export const EditExperimentParam = (): any => {
...
@@ -30,6 +30,7 @@ export const EditExperimentParam = (): any => {
const
{
title
,
field
,
editType
,
maxExecDuration
,
maxTrialNum
,
trialConcurrency
,
updateOverviewPage
}
=
useContext
(
const
{
title
,
field
,
editType
,
maxExecDuration
,
maxTrialNum
,
trialConcurrency
,
updateOverviewPage
}
=
useContext
(
EditExpeParamContext
EditExpeParamContext
);
);
const
originMaxDurationStr
=
EXPERIMENT
.
profile
.
params
.
maxExperimentDuration
;
const
{
maxDurationUnit
,
changeMaxDurationUnit
}
=
useContext
(
AppContext
);
const
{
maxDurationUnit
,
changeMaxDurationUnit
}
=
useContext
(
AppContext
);
const
[
unit
,
setUnit
]
=
useState
(
maxDurationUnit
);
const
[
unit
,
setUnit
]
=
useState
(
maxDurationUnit
);
let
defaultVal
=
''
;
let
defaultVal
=
''
;
...
@@ -101,13 +102,7 @@ export const EditExperimentParam = (): any => {
...
@@ -101,13 +102,7 @@ export const EditExperimentParam = (): any => {
}
}
if
(
isMaxDuration
)
{
if
(
isMaxDuration
)
{
const
maxDura
=
JSON
.
parse
(
editInputVal
);
const
maxDura
=
JSON
.
parse
(
editInputVal
);
if
(
unit
===
'
m
'
)
{
newProfile
.
params
[
field
]
=
`
${
maxDura
}${
unit
}
`
;
newProfile
.
params
[
field
]
=
maxDura
*
60
;
}
else
if
(
unit
===
'
h
'
)
{
newProfile
.
params
[
field
]
=
maxDura
*
3600
;
}
else
{
newProfile
.
params
[
field
]
=
maxDura
*
24
*
60
*
60
;
}
}
else
{
}
else
{
newProfile
.
params
[
field
]
=
parseInt
(
editInputVal
,
10
);
newProfile
.
params
[
field
]
=
parseInt
(
editInputVal
,
10
);
}
}
...
@@ -118,8 +113,11 @@ export const EditExperimentParam = (): any => {
...
@@ -118,8 +113,11 @@ export const EditExperimentParam = (): any => {
params
:
{
update_type
:
editType
}
params
:
{
update_type
:
editType
}
});
});
if
(
res
.
status
===
200
)
{
if
(
res
.
status
===
200
)
{
if
(
isMaxDuration
)
{
changeMaxDurationUnit
(
unit
);
}
showMessageInfo
(
`Successfully updated experiment's
${
field
}
`
,
'
success
'
);
showMessageInfo
(
`Successfully updated experiment's
${
field
}
`
,
'
success
'
);
changeMaxDurationUnit
(
unit
);
updateOverviewPage
(
);
}
}
}
catch
(
error
)
{
}
catch
(
error
)
{
if
(
error
.
response
&&
error
.
response
.
data
.
error
)
{
if
(
error
.
response
&&
error
.
response
.
data
.
error
)
{
...
@@ -132,9 +130,14 @@ export const EditExperimentParam = (): any => {
...
@@ -132,9 +130,14 @@ export const EditExperimentParam = (): any => {
showMessageInfo
(
`Failed to update trial
${
field
}
\nUnknown error`
,
'
error
'
);
showMessageInfo
(
`Failed to update trial
${
field
}
\nUnknown error`
,
'
error
'
);
}
}
setEditValInput
(
defaultVal
);
setEditValInput
(
defaultVal
);
// confirm trial config panel val
if
(
isMaxDuration
)
{
newProfile
.
params
[
field
]
=
originMaxDurationStr
;
}
else
{
newProfile
.
params
[
field
]
=
beforeParam
;
}
}
}
showPencil
();
showPencil
();
updateOverviewPage
();
}
}
function
cancelEdit
():
void
{
function
cancelEdit
():
void
{
...
@@ -162,7 +165,7 @@ export const EditExperimentParam = (): any => {
...
@@ -162,7 +165,7 @@ export const EditExperimentParam = (): any => {
<
EditExpeParamContext
.
Consumer
>
<
EditExpeParamContext
.
Consumer
>
{
(
value
):
React
.
ReactNode
=>
{
{
(
value
):
React
.
ReactNode
=>
{
let
editClassName
=
''
;
let
editClassName
=
''
;
if
(
value
.
field
===
'
maxEx
ec
Duration
'
)
{
if
(
value
.
field
===
'
maxEx
periment
Duration
'
)
{
editClassName
=
isShowPencil
?
'
noEditDuration
'
:
'
editDuration
'
;
editClassName
=
isShowPencil
?
'
noEditDuration
'
:
'
editDuration
'
;
}
}
return
(
return
(
...
...
ts/webui/src/components/overview/count/ExpDuration.tsx
View file @
063d6b74
...
@@ -50,7 +50,7 @@ export const ExpDuration = (): any => (
...
@@ -50,7 +50,7 @@ export const ExpDuration = (): any => (
<
EditExpeParamContext
.
Provider
<
EditExpeParamContext
.
Provider
value
=
{
{
value
=
{
{
editType
:
CONTROLTYPE
[
0
],
editType
:
CONTROLTYPE
[
0
],
field
:
'
maxEx
ec
Duration
'
,
field
:
'
maxEx
periment
Duration
'
,
title
:
'
Max duration
'
,
title
:
'
Max duration
'
,
maxExecDuration
:
maxExecDurationStr
,
maxExecDuration
:
maxExecDurationStr
,
maxTrialNum
:
EXPERIMENT
.
maxTrialNumber
,
maxTrialNum
:
EXPERIMENT
.
maxTrialNumber
,
...
...
ts/webui/src/components/overview/count/TrialCount.tsx
View file @
063d6b74
...
@@ -89,7 +89,7 @@ export const TrialCount = (): any => {
...
@@ -89,7 +89,7 @@ export const TrialCount = (): any => {
<
EditExpeParamContext
.
Provider
<
EditExpeParamContext
.
Provider
value
=
{
{
value
=
{
{
title
:
MAX_TRIAL_NUMBERS
,
title
:
MAX_TRIAL_NUMBERS
,
field
:
'
maxTrialNum
'
,
field
:
'
maxTrialNum
ber
'
,
editType
:
CONTROLTYPE
[
1
],
editType
:
CONTROLTYPE
[
1
],
maxExecDuration
:
''
,
maxExecDuration
:
''
,
maxTrialNum
:
EXPERIMENT
.
maxTrialNumber
,
maxTrialNum
:
EXPERIMENT
.
maxTrialNumber
,
...
...
ts/webui/src/components/slideNav/TrialConfigPanel.tsx
View file @
063d6b74
...
@@ -3,8 +3,7 @@ import { Stack, Panel, PrimaryButton } from '@fluentui/react';
...
@@ -3,8 +3,7 @@ import { Stack, Panel, PrimaryButton } from '@fluentui/react';
import
{
EXPERIMENT
}
from
'
../../static/datamodel
'
;
import
{
EXPERIMENT
}
from
'
../../static/datamodel
'
;
import
MonacoEditor
from
'
react-monaco-editor
'
;
import
MonacoEditor
from
'
react-monaco-editor
'
;
import
{
MONACO
}
from
'
../../static/const
'
;
import
{
MONACO
}
from
'
../../static/const
'
;
import
{
AppContext
}
from
'
../../App
'
;
import
{
convertDuration
,
caclMonacoEditorHeight
}
from
'
../../static/function
'
;
import
{
convertDuration
,
convertTimeAsUnit
,
caclMonacoEditorHeight
}
from
'
../../static/function
'
;
import
{
prettyStringify
}
from
'
../../static/json_util
'
;
import
{
prettyStringify
}
from
'
../../static/json_util
'
;
import
lodash
from
'
lodash
'
;
import
lodash
from
'
lodash
'
;
import
'
../../static/style/logDrawer.scss
'
;
import
'
../../static/style/logDrawer.scss
'
;
...
@@ -69,56 +68,45 @@ class TrialConfigPanel extends React.Component<LogDrawerProps, LogDrawerState> {
...
@@ -69,56 +68,45 @@ class TrialConfigPanel extends React.Component<LogDrawerProps, LogDrawerState> {
const
prettyWidth
=
innerWidth
>
1400
?
100
:
60
;
const
prettyWidth
=
innerWidth
>
1400
?
100
:
60
;
const
showProfile
=
JSON
.
stringify
(
profile
,
filter
,
2
);
return
(
return
(
<
AppContext
.
Consumer
>
<
Stack
>
{
(
value
):
React
.
ReactNode
=>
{
<
Panel
const
unit
=
value
.
maxDurationUnit
;
isOpen
=
{
true
}
profile
.
params
.
maxExecDuration
=
`
${
convertTimeAsUnit
(
hasCloseButton
=
{
false
}
unit
,
isFooterAtBottom
=
{
true
}
profile
.
params
.
maxExecDuration
isLightDismiss
=
{
true
}
)}${
unit
}
`
;
onLightDismissClick
=
{
hideConfigPanel
}
const
showProfile
=
JSON
.
stringify
(
profile
,
filter
,
2
);
>
return
(
<
div
className
=
'panel'
>
<
Stack
>
{
panelName
===
'
search space
'
?
(
<
Panel
<
div
>
isOpen
=
{
true
}
<
div
className
=
'panelName'
>
Search space
</
div
>
hasCloseButton
=
{
false
}
<
MonacoEditor
isFooterAtBottom
=
{
true
}
height
=
{
monacoEditorHeight
}
isLightDismiss
=
{
true
}
language
=
'json'
onLightDismissClick
=
{
hideConfigPanel
}
theme
=
'vs-light'
>
value
=
{
prettyStringify
(
EXPERIMENT
.
searchSpace
,
prettyWidth
,
2
)
}
<
div
className
=
'panel'
>
options
=
{
MONACO
}
{
panelName
===
'
search space
'
?
(
/>
<
div
>
</
div
>
<
div
className
=
'panelName'
>
Search space
</
div
>
)
:
(
<
MonacoEditor
<
div
className
=
'profile'
>
height
=
{
monacoEditorHeight
}
<
div
className
=
'panelName'
>
Config
</
div
>
language
=
'json'
<
MonacoEditor
theme
=
'vs-light'
width
=
'100%'
value
=
{
prettyStringify
(
EXPERIMENT
.
searchSpace
,
prettyWidth
,
2
)
}
height
=
{
monacoEditorHeight
}
options
=
{
MONACO
}
language
=
'json'
/>
theme
=
'vs-light'
</
div
>
value
=
{
showProfile
}
)
:
(
options
=
{
MONACO
}
<
div
className
=
'profile'
>
/>
<
div
className
=
'panelName'
>
Config
</
div
>
</
div
>
<
MonacoEditor
)
}
width
=
'100%'
<
PrimaryButton
text
=
'Close'
className
=
'configClose'
onClick
=
{
hideConfigPanel
}
/>
height
=
{
monacoEditorHeight
}
</
div
>
language
=
'json'
</
Panel
>
theme
=
'vs-light'
</
Stack
>
value
=
{
showProfile
}
options
=
{
MONACO
}
/>
</
div
>
)
}
<
PrimaryButton
text
=
'Close'
className
=
'configClose'
onClick
=
{
hideConfigPanel
}
/>
</
div
>
</
Panel
>
</
Stack
>
);
}
}
</
AppContext
.
Consumer
>
);
);
}
}
}
}
...
...
Prev
1
2
3
4
5
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