diff --git a/README.md b/README.md index 53ad6b5537..64c49ff943 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ Note: If you are in docker container (as root), please remove `--user` from the * We only support Linux (Ubuntu 16.04 or higher) in our current stage. * Run the following commands in an environment that has `python >= 3.5`, `git` and `wget`. ```bash - git clone -b v0.3.3 https://github.com/Microsoft/nni.git + git clone -b v0.3.4 https://github.com/Microsoft/nni.git cd nni source install.sh ``` @@ -47,7 +47,7 @@ Note: If you are in docker container (as root), please remove `--user` from the The following example is an experiment built on TensorFlow. Make sure you have **TensorFlow installed** before running it. * Download the examples via clone the source code. ```bash - git clone -b v0.3.3 https://github.com/Microsoft/nni.git + git clone -b v0.3.4 https://github.com/Microsoft/nni.git ``` * Run the mnist example. ```bash diff --git a/deployment/docker/Dockerfile b/deployment/docker/Dockerfile index a14cb0ab37..3db87f093a 100644 --- a/deployment/docker/Dockerfile +++ b/deployment/docker/Dockerfile @@ -18,7 +18,7 @@ # DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -FROM nvidia/cuda:9.0-cudnn7-devel-ubuntu16.04 +FROM nvidia/cuda:9.0-cudnn7-runtime-ubuntu16.04 LABEL maintainer='Microsoft NNI Team' @@ -53,7 +53,7 @@ RUN python3 -m pip --no-cache-dir install \ # #Install NNI # -RUN python3 -m pip install --user nni +RUN python3 -m pip install nni # #Tensorflow 1.10.0 @@ -68,6 +68,6 @@ RUN python3 -m pip --no-cache-dir install Keras==2.1.6 #sklearn RUN python3 -m pip --no-cache-dir install scikit-learn -ENV PATH=/usr/local/nvidia/bin:/usr/local/cuda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/root/.local/bin:/usr/bin: +ENV PATH=/usr/local/nvidia/bin:/usr/local/cuda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/root/.local/bin:/usr/bin:/bin:/sbin WORKDIR /root \ No newline at end of file diff --git a/deployment/pypi/setup.py b/deployment/pypi/setup.py index ddaa4ff0af..3214261d88 100644 --- a/deployment/pypi/setup.py +++ b/deployment/pypi/setup.py @@ -11,7 +11,7 @@ setuptools.setup( name = 'nni', - version = '0.3.2', + version = '0.3.4', author = 'Microsoft NNI team', author_email = 'nni@microsoft.com', description = 'Neural Network Intelligence package', @@ -32,7 +32,8 @@ 'pyyaml', 'psutil', 'requests', - 'astor' + 'astor', + 'pyhdfs' ], classifiers = [ 'Programming Language :: Python :: 3', diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 4d0f488082..9fc7ff3c96 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -28,7 +28,7 @@ When raising issues, please specify the following: Provide PRs with appropriate tags for bug fixes or enhancements to the source code. Do follow the correct naming conventions and code styles when you work on and do try to implement all code reviews along the way. -If you are looking for How to go about contributing and debugging the NNI source code, you can refer our [How to Contribute](./HowToContribute.md) file in the `docs` folder. +If you are looking for How to develop and debug the NNI source code, you can refer to [How to set up NNI developer environment doc](./SetupNNIDeveloperEnvironment.md) file in the `docs` folder. Similarly for [writing trials](./WriteYourTrial.md) or [starting experiments](StartExperiment.md). For everything else, refer [here](https://github.com/Microsoft/nni/tree/master/docs). diff --git a/docs/GetStarted.md b/docs/GetStarted.md index cde8a3cb85..096804da2a 100644 --- a/docs/GetStarted.md +++ b/docs/GetStarted.md @@ -18,7 +18,7 @@ * __Install NNI through source code__ - git clone -b v0.3.3 https://github.com/Microsoft/nni.git + git clone -b v0.3.4 https://github.com/Microsoft/nni.git cd nni source install.sh diff --git a/docs/InstallNNI_Ubuntu.md b/docs/InstallNNI_Ubuntu.md index 3256028db0..d76b09dd86 100644 --- a/docs/InstallNNI_Ubuntu.md +++ b/docs/InstallNNI_Ubuntu.md @@ -16,7 +16,7 @@ * __Install NNI through source code__ - git clone -b v0.3.3 https://github.com/Microsoft/nni.git + git clone -b v0.3.4 https://github.com/Microsoft/nni.git cd nni source install.sh diff --git a/docs/NNICTLDOC.md b/docs/NNICTLDOC.md index bbdbd3aac3..1c864ca515 100644 --- a/docs/NNICTLDOC.md +++ b/docs/NNICTLDOC.md @@ -15,6 +15,7 @@ nnictl experiment nnictl config nnictl log nnictl webui +nnictl tensorboard ``` ### Manage an experiment * __nnictl create__ @@ -122,6 +123,23 @@ nnictl webui | ------ | ------ | ------ |------ | | id| False| |ID of the experiment you want to set| | --value, -v| True| |the experiment duration will be NUMBER seconds. SUFFIX may be 's' for seconds (the default), 'm' for minutes, 'h' for hours or 'd' for days.| + + * __nnictl update trialnum__ + * Description + + You can use this command to update an experiment's maxtrialnum. + + * Usage + + nnictl update trialnum [OPTIONS] + + Options: + + | Name, shorthand | Required|Default | Description | + | ------ | ------ | ------ |------ | + | id| False| |ID of the experiment you want to set| + | --value, -v| True| |the new number of maxtrialnum you want to set| + * __nnictl trial__ diff --git a/docs/SetupNNIDeveloperEnvironment.md b/docs/SetupNNIDeveloperEnvironment.md index a9a9cb9d01..ea93ce60e2 100644 --- a/docs/SetupNNIDeveloperEnvironment.md +++ b/docs/SetupNNIDeveloperEnvironment.md @@ -47,7 +47,7 @@ And open WebUI to check if everything is OK **6. Redeploy** -After you change some code, just use **step 4** to rebuild your code, then the change will take effect immediately +After the code changes, use **step 3** to rebuild your codes, then the changes will take effect immediately. --- At last, wish you have a wonderful day. diff --git a/examples/trials/mnist-annotation/mnist.py b/examples/trials/mnist-annotation/mnist.py index 69ef283336..829c2fe65d 100644 --- a/examples/trials/mnist-annotation/mnist.py +++ b/examples/trials/mnist-annotation/mnist.py @@ -157,8 +157,8 @@ def main(params): ''' # Import data mnist = input_data.read_data_sets(params['data_dir'], one_hot=True) - print('Mnist download data down.') - logger.debug('Mnist download data down.') + print('Mnist download data done.') + logger.debug('Mnist download data done.') # Create the model # Build the graph for the deep net @@ -180,15 +180,15 @@ def main(params): test_acc = 0.0 with tf.Session() as sess: sess.run(tf.global_variables_initializer()) - """@nni.variable(nni.choice(50, 250, 500), name=batch_num)""" - batch_num = params['batch_num'] - for i in range(batch_num): - batch = mnist.train.next_batch(batch_num) - """@nni.variable(nni.choice(1, 5), name=dropout_rate)""" + """@nni.variable(nni.choice(1, 4, 8, 16, 32), name=batch_size)""" + batch_size = params['batch_size'] + for i in range(params['batch_num']): + batch = mnist.train.next_batch(batch_size) + """@nni.variable(nni.choice(0.5, 0.9), name=dropout_rate)""" dropout_rate = params['dropout_rate'] mnist_network.train_step.run(feed_dict={mnist_network.images: batch[0], mnist_network.labels: batch[1], - mnist_network.keep_prob: dropout_rate} + mnist_network.keep_prob: 1 - dropout_rate} ) if i % 100 == 0: @@ -224,7 +224,8 @@ def generate_defualt_params(): 'pool_size': 2, 'hidden_size': 1024, 'learning_rate': 1e-4, - 'batch_num': 200} + 'batch_num': 2000, + 'batch_size': 32} return params diff --git a/examples/trials/mnist-smartparam/mnist.py b/examples/trials/mnist-smartparam/mnist.py index 2b90018b52..28b9fb8b31 100644 --- a/examples/trials/mnist-smartparam/mnist.py +++ b/examples/trials/mnist-smartparam/mnist.py @@ -180,13 +180,13 @@ def main(params): test_acc = 0.0 with tf.Session() as sess: sess.run(tf.global_variables_initializer()) - batch_num = nni.choice(50, 250, 500, name='batch_num') - for i in range(batch_num): - batch = mnist.train.next_batch(batch_num) - dropout_rate = nni.choice(1, 5, name='dropout_rate') + batch_size = nni.choice(1, 4, 8, 16, 32, name='batch_size') + for i in range(2000): + batch = mnist.train.next_batch(batch_size) + dropout_rate = nni.choice(0.5, 0.9, name='dropout_rate') mnist_network.train_step.run(feed_dict={mnist_network.images: batch[0], mnist_network.labels: batch[1], - mnist_network.keep_prob: dropout_rate} + mnist_network.keep_prob: 1 - dropout_rate} ) if i % 100 == 0: @@ -223,6 +223,7 @@ def generate_defualt_params(): if __name__ == '__main__': try: + nni.get_next_parameter() main(generate_defualt_params()) except Exception as exception: logger.exception(exception) diff --git a/examples/trials/mnist/config_assessor.yml b/examples/trials/mnist/config_assessor.yml index 862a262a28..d5a3c33d23 100644 --- a/examples/trials/mnist/config_assessor.yml +++ b/examples/trials/mnist/config_assessor.yml @@ -2,10 +2,10 @@ authorName: default experimentName: example_mnist trialConcurrency: 1 maxExecDuration: 1h -maxTrialNum: 1 +maxTrialNum: 20 #choice: local, remote trainingServicePlatform: local -searchSpacePath: ~/nni/examples/trials/mnist/search_space.json +searchSpacePath: search_space.json #choice: true, false useAnnotation: false tuner: @@ -23,5 +23,5 @@ assessor: optimize_mode: maximize trial: command: python3 mnist.py - codeDir: ~/nni/examples/trials/mnist + codeDir: . gpuNum: 0 diff --git a/examples/trials/mnist/mnist.py b/examples/trials/mnist/mnist.py index d5c6347b5a..d6384ecdef 100644 --- a/examples/trials/mnist/mnist.py +++ b/examples/trials/mnist/mnist.py @@ -173,10 +173,10 @@ def main(params): with tf.Session() as sess: sess.run(tf.global_variables_initializer()) for i in range(params['batch_num']): - batch = mnist.train.next_batch(params['batch_num']) + batch = mnist.train.next_batch(params['batch_size']) mnist_network.train_step.run(feed_dict={mnist_network.images: batch[0], mnist_network.labels: batch[1], - mnist_network.keep_prob: params['dropout_rate']} + mnist_network.keep_prob: 1 - params['dropout_rate']} ) if i % 100 == 0: @@ -212,7 +212,8 @@ def generate_default_params(): 'pool_size': 2, 'hidden_size': 1024, 'learning_rate': 1e-4, - 'batch_num': 200} + 'batch_num': 2000, + 'batch_size': 32} return params diff --git a/examples/trials/mnist/search_space.json b/examples/trials/mnist/search_space.json index 1d416cbfa6..c9b68a7a4f 100644 --- a/examples/trials/mnist/search_space.json +++ b/examples/trials/mnist/search_space.json @@ -1,6 +1,7 @@ { - "dropout_rate":{"_type":"uniform","_value":[0.1,0.5]}, + "dropout_rate":{"_type":"uniform","_value":[0.5, 0.9]}, "conv_size":{"_type":"choice","_value":[2,3,5,7]}, "hidden_size":{"_type":"choice","_value":[124, 512, 1024]}, + "batch_size": {"_type":"choice", "_value": [1, 4, 8, 16, 32]}, "learning_rate":{"_type":"choice","_value":[0.0001, 0.001, 0.01, 0.1]} } diff --git a/setup.py b/setup.py index 8a09d581b6..7f59348054 100644 --- a/setup.py +++ b/setup.py @@ -35,7 +35,7 @@ def run(self): setup( name = 'nni', - version = '0.3.2', + version = '0.3.4', author = 'Microsoft NNI Team', author_email = 'nni@microsoft.com', description = 'Neural Network Intelligence project', diff --git a/src/nni_manager/rest_server/restValidationSchemas.ts b/src/nni_manager/rest_server/restValidationSchemas.ts index f429c503ea..a95c81765c 100644 --- a/src/nni_manager/rest_server/restValidationSchemas.ts +++ b/src/nni_manager/rest_server/restValidationSchemas.ts @@ -94,7 +94,9 @@ export namespace ValidationSchemas { params: joi.object(STARTEXPERIMENT.body).required(), execDuration: joi.number().required(), startTime: joi.number(), - endTime: joi.number() + endTime: joi.number(), + logDir: joi.string(), + maxSequenceId: joi.number() } }; export const STARTTENSORBOARD = { diff --git a/src/nni_manager/training_service/local/localTrainingService.ts b/src/nni_manager/training_service/local/localTrainingService.ts index 6dbde68f87..9927f0c4f5 100644 --- a/src/nni_manager/training_service/local/localTrainingService.ts +++ b/src/nni_manager/training_service/local/localTrainingService.ts @@ -78,7 +78,7 @@ class LocalTrialJobDetail implements TrialJobDetail { public pid?: number; constructor(id: string, status: TrialJobStatus, submitTime: number, - workingDirectory: string, form: JobApplicationForm, sequenceId: number) { + workingDirectory: string, form: JobApplicationForm, sequenceId: number) { this.id = id; this.status = status; this.submitTime = submitTime; @@ -283,13 +283,13 @@ class LocalTrainingService implements TrainingService { public getClusterMetadata(key: string): Promise { switch (key) { case TrialConfigMetadataKey.TRIAL_CONFIG: - let getResult : Promise; - if(!this.localTrailConfig) { + let getResult: Promise; + if (!this.localTrailConfig) { getResult = Promise.reject(new NNIError(NNIErrorNames.NOT_FOUND, `${key} is never set yet`)); } else { - getResult = Promise.resolve(!this.localTrailConfig? '' : JSON.stringify(this.localTrailConfig)); + getResult = Promise.resolve(!this.localTrailConfig ? '' : JSON.stringify(this.localTrailConfig)); } - return getResult; + return getResult; default: return Promise.reject(new NNIError(NNIErrorNames.NOT_FOUND, 'Key not found')); } @@ -297,7 +297,7 @@ class LocalTrainingService implements TrainingService { public cleanUp(): Promise { this.stopping = true; - for(const stream of this.streams) { + for (const stream of this.streams) { stream.destroy(); } return Promise.resolve(); @@ -359,7 +359,7 @@ class LocalTrainingService implements TrainingService { await cpp.exec(`mkdir -p ${trialJobDetail.workingDirectory}`); await cpp.exec(`mkdir -p ${path.join(trialJobDetail.workingDirectory, '.nni')}`); await cpp.exec(`touch ${path.join(trialJobDetail.workingDirectory, '.nni', 'metrics')}`); - await fs.promises.writeFile(path.join(trialJobDetail.workingDirectory, 'run.sh'), runScriptLines.join('\n'), { encoding: 'utf8' }); + await fs.promises.writeFile(path.join(trialJobDetail.workingDirectory, 'run.sh'), runScriptLines.join('\n'), { encoding: 'utf8', mode: 0o777 }); await this.writeParameterFile(trialJobDetail.workingDirectory, (trialJobDetail.form).hyperParameters); await this.writeSequenceIdFile(trialJobId); const process: cp.ChildProcess = cp.exec(`bash ${path.join(trialJobDetail.workingDirectory, 'run.sh')}`); diff --git a/src/sdk/pynni/nni/trial.py b/src/sdk/pynni/nni/trial.py index 35d0397795..14c64569c1 100644 --- a/src/sdk/pynni/nni/trial.py +++ b/src/sdk/pynni/nni/trial.py @@ -47,6 +47,7 @@ def get_next_parameter(): return _params['parameters'] def get_current_parameter(tag): + global _params if _params is None: return None return _params['parameters'][tag] diff --git a/src/webui/src/components/Overview.tsx b/src/webui/src/components/Overview.tsx index 28584c1466..80a5fe2591 100644 --- a/src/webui/src/components/Overview.tsx +++ b/src/webui/src/components/Overview.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import axios from 'axios'; -import { Row, Col } from 'antd'; +import { Row, Col, Button } from 'antd'; import { MANAGER_IP } from '../static/const'; import { Experiment, TableObj, @@ -20,10 +20,11 @@ require('../static/style/accuracy.css'); require('../static/style/table.scss'); require('../static/style/overviewTitle.scss'); -interface SessionState { +interface OverviewState { tableData: Array; searchSpace: object; status: string; + errorStr: string; trialProfile: Experiment; option: object; noData: string; @@ -31,9 +32,10 @@ interface SessionState { bestAccuracy: string; accNodata: string; trialNumber: TrialNumber; + downBool: boolean; } -class Overview extends React.Component<{}, SessionState> { +class Overview extends React.Component<{}, OverviewState> { public _isMounted = false; public intervalID = 0; @@ -44,6 +46,7 @@ class Overview extends React.Component<{}, SessionState> { this.state = { searchSpace: {}, status: '', + errorStr: '', trialProfile: { id: '', author: '', @@ -81,7 +84,8 @@ class Overview extends React.Component<{}, SessionState> { runTrial: 0, unknowTrial: 0, totalCurrentTrial: 0 - } + }, + downBool: false }; } @@ -124,8 +128,8 @@ class Overview extends React.Component<{}, SessionState> { switch (key) { case 'loguniform': case 'qloguniform': - const a = Math.pow(10, value[0]); - const b = Math.pow(10, value[1]); + const a = Math.pow(Math.E, value[0]); + const b = Math.pow(Math.E, value[1]); value = [a, b]; searchSpace[item]._value = value; break; @@ -148,17 +152,30 @@ class Overview extends React.Component<{}, SessionState> { } } }); + this.checkStatus(); + + } + checkStatus = () => { axios(`${MANAGER_IP}/check-status`, { method: 'GET' }) .then(res => { if (res.status === 200 && this._isMounted) { - this.setState({ - status: res.data.status - }); + const errors = res.data.errors; + if (errors.length !== 0) { + this.setState({ + status: res.data.status, + errorStr: res.data.errors[0] + }); + } else { + this.setState({ + status: res.data.status, + }); + } } }); + } showTrials = () => { @@ -263,6 +280,9 @@ class Overview extends React.Component<{}, SessionState> { } downExperimentContent = () => { + this.setState(() => ({ + downBool: true + })); axios .all([ axios.get(`${MANAGER_IP}/experiment`), @@ -307,6 +327,9 @@ class Overview extends React.Component<{}, SessionState> { eventMouse.initEvent('click', false, false); downTag.dispatchEvent(eventMouse); } + this.setState(() => ({ + downBool: false + })); } })); } @@ -388,15 +411,30 @@ class Overview extends React.Component<{}, SessionState> { accuracyData, accNodata, status, + errorStr, trialNumber, - bestAccuracy + bestAccuracy, + downBool } = this.state; return (
{/* status and experiment block */} - - + + + + + + + @@ -408,6 +446,7 @@ class Overview extends React.Component<{}, SessionState> { trialProfile={trialProfile} bestAccuracy={bestAccuracy} status={status} + errors={errorStr} /> {/* experiment parameters search space tuner assessor... */} diff --git a/src/webui/src/components/overview/BasicInfo.tsx b/src/webui/src/components/overview/BasicInfo.tsx index d1a500f978..8abef523c1 100644 --- a/src/webui/src/components/overview/BasicInfo.tsx +++ b/src/webui/src/components/overview/BasicInfo.tsx @@ -52,7 +52,7 @@ class BasicInfo extends React.Component {

LogPath

-
+
{trialProfile.logDir} diff --git a/src/webui/src/components/overview/Progress.tsx b/src/webui/src/components/overview/Progress.tsx index cf1022ba57..45de55fb59 100644 --- a/src/webui/src/components/overview/Progress.tsx +++ b/src/webui/src/components/overview/Progress.tsx @@ -2,17 +2,20 @@ import * as React from 'react'; import { Row, Col, + Popover } from 'antd'; import { Experiment, TrialNumber } from '../../static/interface'; import { convertTime } from '../../static/function'; import ProgressBar from './ProgressItem'; import '../../static/style/progress.scss'; +import '../../static/style/probar.scss'; interface ProgressProps { trialProfile: Experiment; trialNumber: TrialNumber; bestAccuracy: string; status: string; + errors: string; } class Progressed extends React.Component { @@ -24,7 +27,7 @@ class Progressed extends React.Component { render() { const { trialProfile, trialNumber, bestAccuracy, - status + status, errors } = this.props; // remaining time const bar2 = trialNumber.totalCurrentTrial - trialNumber.waitTrial - trialNumber.unknowTrial; @@ -32,23 +35,49 @@ class Progressed extends React.Component { const percent = (trialProfile.execDuration / trialProfile.maxDuration) * 100; const runDuration = convertTime(trialProfile.execDuration); const remaining = convertTime(trialProfile.maxDuration - trialProfile.execDuration); - + let errorContent; + if (errors !== '') { + errorContent = ( +
+ {errors} +
+ ); + } return ( - +

Status

-
{status}
+
+ {status} + { + status === 'ERROR' + ? + + i + + : + + } + +
diff --git a/src/webui/src/components/overview/ProgressItem.tsx b/src/webui/src/components/overview/ProgressItem.tsx index b911118ee4..652cd3864f 100644 --- a/src/webui/src/components/overview/ProgressItem.tsx +++ b/src/webui/src/components/overview/ProgressItem.tsx @@ -6,6 +6,7 @@ interface ProItemProps { percent: number; description: string; maxString: string; + bgclass: string; } class ProgressBar extends React.Component { @@ -16,11 +17,11 @@ class ProgressBar extends React.Component { } render() { - const { who, percent, description, maxString } = this.props; + const { who, percent, description, maxString, bgclass } = this.props; return (
- +
{who}
@@ -34,8 +35,8 @@ class ProgressBar extends React.Component { />
- 0 - {maxString} + 0 + {maxString}
diff --git a/src/webui/src/components/overview/TrialProfile.tsx b/src/webui/src/components/overview/TrialProfile.tsx index 8198aea3a6..3a429d62b6 100644 --- a/src/webui/src/components/overview/TrialProfile.tsx +++ b/src/webui/src/components/overview/TrialProfile.tsx @@ -23,7 +23,7 @@ class TrialInfo extends React.Component { clusterMetaData: tiralProInfo.clusterMetaData ? tiralProInfo.clusterMetaData : undefined }); return ( -
+
                     {JSON.stringify(showProInfo[0], null, 4)}
                 
diff --git a/src/webui/src/index.css b/src/webui/src/index.css index d3f609f92d..139ac33243 100644 --- a/src/webui/src/index.css +++ b/src/webui/src/index.css @@ -49,9 +49,6 @@ table { border-collapse: collapse; border-spacing: 0; } -pre{ - overflow: hidden; -} @font-face { font-family: 'Segoe'; src: url('./static/font/SegoePro-Regular.ttf'); diff --git a/src/webui/src/static/img/icon/download.png b/src/webui/src/static/img/icon/download.png new file mode 100644 index 0000000000..4182f1a70e Binary files /dev/null and b/src/webui/src/static/img/icon/download.png differ diff --git a/src/webui/src/static/style/button.scss b/src/webui/src/static/style/button.scss index 73f373df08..37b407c97f 100644 --- a/src/webui/src/static/style/button.scss +++ b/src/webui/src/static/style/button.scss @@ -2,7 +2,6 @@ Button.changeBtu, Button.changeBtu:hover, Button.changeBtu:focus{ background-color: #3c8dbc; border-color: #3c8dbc; line-height: 30px; - font-size: 16px; } Button.tableButton{ diff --git a/src/webui/src/static/style/logPath.scss b/src/webui/src/static/style/logPath.scss index 0f328d4e09..d9786e7998 100644 --- a/src/webui/src/static/style/logPath.scss +++ b/src/webui/src/static/style/logPath.scss @@ -1,5 +1,4 @@ .logpath{ - margin-bottom: 10px; margin-left: 10px; .logName{ diff --git a/src/webui/src/static/style/overview.scss b/src/webui/src/static/style/overview.scss index 1c991e136a..452df13ebc 100644 --- a/src/webui/src/static/style/overview.scss +++ b/src/webui/src/static/style/overview.scss @@ -44,3 +44,36 @@ .main{ margin: 9px 0; } + +.profile{ + padding: 0 20px; + pre{ + overflow: inherit; + } +} + +.exbgcolor { + background: #b3b3b3; + + .download{ + height: 30px; + border: 1px solid #fff; + border-radius: 0; + margin-top: 4px; + background-color: #0071BC; + + span{ + font-family: 'Segoe'; + font-size: 14px; + } + + img{ + height: 14px; + margin-left: 10px; + margin-top: -6px; + } + } +} +.exbgcolor .download:hover{ + border: 1px solid #fff; +} \ No newline at end of file diff --git a/src/webui/src/static/style/probar.scss b/src/webui/src/static/style/probar.scss new file mode 100644 index 0000000000..c6ff7549f7 --- /dev/null +++ b/src/webui/src/static/style/probar.scss @@ -0,0 +1,61 @@ +#barBack{ + /* status: 'INITIALIZED' | 'EXPERIMENT_RUNNING' | 'ERROR' | 'STOPPING' | 'STOPPED' | 'DONE' */ + .EXPERIMENT_RUNNING, .STOPPING, .INITIALIZED{ + /* specific status color */ + color: #0071bc; + .ant-progress-bg { + background-color: #0071bc; + } + .ant-progress-text{ + color: #0071bc; + } + } + .DONE, .STOPPED{ + color: #009245; + .ant-progress-bg { + background-color: #009245; + } + .ant-progress-text{ + color: #009245; + } + } + .ERROR{ + color: #eb0716; + .ant-progress-bg { + background-color: #eb0716; + } + .ant-progress-text{ + color: #eb0716; + } + + } + .ant-progress-bg{ + border-radius: 0 !important; + } + .ant-progress-status-success .ant-progress-bg{ + border-radius: 0 12px 12px 0 !important; + } +} + +.errorBtn{ + margin-left: 15px; + display: inline-block; + width: 18px; + height: 18px; + line-height: 18px; + text-align: center; + font-size: 14px; + border: 1px solid #4d4d4d; + border-radius: 50%; + background-color: #4d4d4d; + color: #fff; +} +.errorBtn:hover{ + cursor: pointer; +} + +.errors{ + width: 240px; + font-size: 14px; + color: #212121; +} diff --git a/src/webui/src/static/style/progress.scss b/src/webui/src/static/style/progress.scss index 39d7deac02..dccae5fe9c 100644 --- a/src/webui/src/static/style/progress.scss +++ b/src/webui/src/static/style/progress.scss @@ -17,14 +17,6 @@ border: 2px solid #e6e6e6; border-radius: 0 12px 12px 0 !important; } - .ant-progress-bg { - border-radius: 0 !important; - } - .ant-progress-status-success .ant-progress-bg{ - border-radius: 0 12px 12px 0 !important; - color: #009245; - background-color: #009245; - } .name{ height: 34px; line-height: 30px; @@ -43,6 +35,7 @@ width: 100%; line-height: 24px; font-size: 12px; + color: #212121; .right{ text-align: right; } @@ -74,9 +67,9 @@ .mess{ margin: 10px 0; } - +/* .ant-tooltip-inner{ - white-space: nowrap; min-width: 300px; } +*/ diff --git a/src/webui/src/static/style/table.scss b/src/webui/src/static/style/table.scss index 0929687f69..bd75beebb4 100644 --- a/src/webui/src/static/style/table.scss +++ b/src/webui/src/static/style/table.scss @@ -89,6 +89,8 @@ pre.hyperpar{ text-align: left; line-height: 18px; font-size: 14px; + overflow: hidden; + margin-bottom: 10px; } /* the position of the pagination */ diff --git a/src/webui/src/static/style/tableStatus.css b/src/webui/src/static/style/tableStatus.css index adf9ca21de..6577c5d6c1 100644 --- a/src/webui/src/static/style/tableStatus.css +++ b/src/webui/src/static/style/tableStatus.css @@ -1,38 +1,3 @@ -/* status bgcolor */ -/* -.commonStyle{ - border-radius: 3px; - color: white; -} -.RUNNING{ - padding: 3px 8px; - background: #3c8dbc; -} -.FAILED{ - padding: 3px 24px; - background: #dd4b39; -} -.USER_CANCELED{ - padding: 3px 8px; - background: #FF4500; -} -.SUCCEEDED{ - padding: 3px 6px; - background: #00a65a; -} -.UNKNOWN{ - padding: 3px 15px; - background: #FF8C00; -} -.SYS_CANCELED{ - padding: 3px 24px; - background: red; -} -.WAITING{ - padding: 3px 24px; - background: #008B8B; -} -*/ .RUNNING{ color: #3c8dbc; } diff --git a/src/webui/src/static/style/trialStatus.scss b/src/webui/src/static/style/trialStatus.scss deleted file mode 100644 index 017655399a..0000000000 --- a/src/webui/src/static/style/trialStatus.scss +++ /dev/null @@ -1,44 +0,0 @@ -.hyper{ - width: 98%; - margin: 30px auto; -} -.rungraph{ - width: 100%; -} - -pre.hyperpar{ - text-align: left; -} -.tables{ - width: 100%; -} - -/* the position of the pagination */ -.ant-table-pagination.ant-pagination{ - margin: 16px 0; - float: right; - margin-right: 30px; -} -Button.tableButton{ - background: #3c8dbc; - border-color: #3c8dbc; - height: 28px; - line-height: 28px; - /* padding: 3px 4px; */ -} - -.hyperpar ul, .hyperpar ul li{ - background: none !important; -} -/* kill btn style: delete its own hover style */ -/* after button click the color not change */ -Button.tableButton:hover, Button.tableButton:focus{ - background-color: #3c8dbc; - border-color: #3c8dbc; -} -.ant-modal-title{ - font-size: 20px; -} - - - diff --git a/tools/nni_cmd/launcher.py b/tools/nni_cmd/launcher.py index b0819e52d3..065ce22512 100644 --- a/tools/nni_cmd/launcher.py +++ b/tools/nni_cmd/launcher.py @@ -35,7 +35,6 @@ import time import random import string -import site from pathlib import Path @@ -67,12 +66,8 @@ def start_rest_server(port, platform, mode, config_file_name, experiment_id=None exit(1) print_normal('Starting restful server...') - if os.geteuid() == 0: - site_dir = site.getsitepackages()[0] - else: - site_dir = site.getusersitepackages() - python_dir = str(Path(site_dir).parents[2]) - cmds = ['node', os.path.join(python_dir, 'nni', 'main.js'), '--port', str(port), '--mode', platform, '--start_mode', mode] + base_dir = str(Path(os.path.dirname(__file__)).parents[3]) + cmds = ['node', os.path.join(base_dir, 'nni', 'main.js'), '--port', str(port), '--mode', platform, '--start_mode', mode] if mode == 'resume': cmds += ['--experiment_id', experiment_id] stdout_full_path, stderr_full_path = get_log_path(config_file_name) @@ -83,7 +78,7 @@ def start_rest_server(port, platform, mode, config_file_name, experiment_id=None log_header = LOG_HEADER % str(time_now) stdout_file.write(log_header) stderr_file.write(log_header) - process = Popen(cmds, cwd=os.path.join(python_dir, 'nni'), stdout=stdout_file, stderr=stderr_file) + process = Popen(cmds, cwd=os.path.join(base_dir, 'nni'), stdout=stdout_file, stderr=stderr_file) return process, str(time_now) def set_trial_config(experiment_config, port, config_file_name): diff --git a/tools/setup.py b/tools/setup.py index 09dcf23a57..cdb20f32b3 100644 --- a/tools/setup.py +++ b/tools/setup.py @@ -2,7 +2,7 @@ setuptools.setup( name = 'nnictl', - version = '0.3.2', + version = '0.3.4', packages = setuptools.find_packages(exclude=['*test*']), python_requires = '>=3.5',