amlClient.ts 5.63 KB
Newer Older
SparkSnail's avatar
SparkSnail committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import { Deferred } from 'ts-deferred';
import { PythonShell } from 'python-shell';

export class AMLClient {
    public subscriptionId: string;
    public resourceGroup: string;
    public workspaceName: string;
    public experimentId: string;
    public image: string;
    public scriptName: string;
    public pythonShellClient: undefined | PythonShell;
    public codeDir: string;
    public computeTarget: string;

    constructor(
        subscriptionId: string,
        resourceGroup: string,
        workspaceName: string,
        experimentId: string,
        computeTarget: string,
        image: string,
        scriptName: string,
        codeDir: string,
        ) {
        this.subscriptionId = subscriptionId;
        this.resourceGroup = resourceGroup;
        this.workspaceName = workspaceName;
        this.experimentId = experimentId;
        this.image = image;
        this.scriptName = scriptName;
        this.codeDir = codeDir;
        this.computeTarget = computeTarget;
    }

    public submit(): Promise<string> {
        const deferred: Deferred<string> = new Deferred<string>();
        this.pythonShellClient = new PythonShell('amlUtil.py', {
            scriptPath: './config/aml',
42
            pythonPath: process.platform === 'win32' ? 'python' : 'python3',
SparkSnail's avatar
SparkSnail committed
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
            pythonOptions: ['-u'], // get print results in real-time
            args: [
                '--subscription_id', this.subscriptionId,
                '--resource_group', this.resourceGroup,
                '--workspace_name', this.workspaceName,
                '--compute_target', this.computeTarget,
                '--docker_image', this.image,
                '--experiment_name', `nni_exp_${this.experimentId}`,
                '--script_dir', this.codeDir,
                '--script_name', this.scriptName
              ]
        });
        this.pythonShellClient.on('message', function (envId: any) {
            // received a message sent from the Python script (a simple "print" statement)
            deferred.resolve(envId);
        });
59
        this.monitorError(this.pythonShellClient, deferred);
SparkSnail's avatar
SparkSnail committed
60
61
62
        return deferred.promise;
    }

63
    public stop(): Promise<boolean> {
SparkSnail's avatar
SparkSnail committed
64
65
66
        if (this.pythonShellClient === undefined) {
            throw Error('python shell client not initialized!');
        }
67
        const deferred: Deferred<boolean> = new Deferred<boolean>();
SparkSnail's avatar
SparkSnail committed
68
        this.pythonShellClient.send('stop');
69
70
71
72
73
74
75
76
77
        this.pythonShellClient.on('message', (result: any) => {
            const stopResult = this.parseContent('stop_result', result);
            if (stopResult === 'success') {
                deferred.resolve(true);
            } else if (stopResult === 'failed') {
                deferred.resolve(false);
            }
        });
        return deferred.promise;
SparkSnail's avatar
SparkSnail committed
78
79
80
81
82
83
84
85
    }

    public getTrackingUrl(): Promise<string> {
        const deferred: Deferred<string> = new Deferred<string>();
        if (this.pythonShellClient === undefined) {
            throw Error('python shell client not initialized!');
        }
        this.pythonShellClient.send('tracking_url');
SparkSnail's avatar
SparkSnail committed
86
87
88
89
        this.pythonShellClient.on('message', (status: any) => {
            const trackingUrl = this.parseContent('tracking_url', status);
            if (trackingUrl !== '') {
                deferred.resolve(trackingUrl);
SparkSnail's avatar
SparkSnail committed
90
91
            }
        });
92
        this.monitorError(this.pythonShellClient, deferred);
SparkSnail's avatar
SparkSnail committed
93
94
95
96
97
98
99
100
101
        return deferred.promise;
    }

    public updateStatus(oldStatus: string): Promise<string> {
        const deferred: Deferred<string> = new Deferred<string>();
        if (this.pythonShellClient === undefined) {
            throw Error('python shell client not initialized!');
        }
        this.pythonShellClient.send('update_status');
SparkSnail's avatar
SparkSnail committed
102
103
104
105
        this.pythonShellClient.on('message', (status: any) => {
            let newStatus = this.parseContent('status', status);
            if (newStatus === '') {
                newStatus = oldStatus;
SparkSnail's avatar
SparkSnail committed
106
107
108
            }
            deferred.resolve(newStatus);
        });
109
        this.monitorError(this.pythonShellClient, deferred);
SparkSnail's avatar
SparkSnail committed
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
        return deferred.promise;
    }

    public sendCommand(message: string): void {
        if (this.pythonShellClient === undefined) {
            throw Error('python shell client not initialized!');
        }
        this.pythonShellClient.send(`command:${message}`);
    }

    public receiveCommand(): Promise<any> {
        const deferred: Deferred<any> = new Deferred<any>();
        if (this.pythonShellClient === undefined) {
            throw Error('python shell client not initialized!');
        }
        this.pythonShellClient.send('receive');
SparkSnail's avatar
SparkSnail committed
126
127
128
129
        this.pythonShellClient.on('message', (command: any) => {
            const message = this.parseContent('receive', command);
            if (message !== '') {
                deferred.resolve(JSON.parse(message))
SparkSnail's avatar
SparkSnail committed
130
131
            }
        });
132
        this.monitorError(this.pythonShellClient, deferred);
SparkSnail's avatar
SparkSnail committed
133
134
        return deferred.promise;
    }
135
136
137
138
139
140
141
142
143
144
    
    // Monitor error information in aml python shell client
    private monitorError(pythonShellClient: PythonShell, deferred: Deferred<any>): void {
        pythonShellClient.on('error', function (error: any) {
            deferred.reject(error);
        });
        pythonShellClient.on('close', function (error: any) {
            deferred.reject(error);
        });
    }
SparkSnail's avatar
SparkSnail committed
145
146
147
148
149
150
151
152
153
    
    // Parse command content, command format is {head}:{content}
    public parseContent(head: string, command: string): string {
        const items = command.split(':');
        if (items[0] === head) {
            return command.slice(head.length + 1);
        }
        return '';
    }
SparkSnail's avatar
SparkSnail committed
154
}