"src/targets/vscode:/vscode.git/clone" did not exist on "bc4d01f863511d345d4ecd79f7050ce25dc4396e"
launcher_utils.py 10.6 KB
Newer Older
Deshui Yu's avatar
Deshui Yu committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# Copyright (c) Microsoft Corporation
# All rights reserved.
#
# MIT License
#
# Permission is hereby granted, free of charge,
# to any person obtaining a copy of this software and associated
# documentation files (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and
# to permit persons to whom the Software is furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
# 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.

import os
22
import json
23
from .config_schema import LOCAL_CONFIG_SCHEMA, REMOTE_CONFIG_SCHEMA, PAI_CONFIG_SCHEMA, KUBEFLOW_CONFIG_SCHEMA
SparkSnail's avatar
SparkSnail committed
24
from .common_utils import get_json_content, print_error, print_warning
25
26
27
28
29
30
31
32
33

def expand_path(experiment_config, key):
    '''Change '~' to user home directory'''
    if experiment_config.get(key):
        experiment_config[key] = os.path.expanduser(experiment_config[key])

def parse_relative_path(root_path, experiment_config, key):
    '''Change relative path to absolute path'''
    if experiment_config.get(key) and not os.path.isabs(experiment_config.get(key)):
SparkSnail's avatar
SparkSnail committed
34
35
36
37
        absolute_path = os.path.join(root_path, experiment_config.get(key))
        print_warning('expand %s: %s to %s ' % (key, experiment_config[key], absolute_path))
        experiment_config[key] = absolute_path

38
def parse_time(experiment_config):
Deshui Yu's avatar
Deshui Yu committed
39
    '''Parse time format'''
40
    unit = experiment_config['maxExecDuration'][-1]
Deshui Yu's avatar
Deshui Yu committed
41
    if unit not in ['s', 'm', 'h', 'd']:
42
43
        print_error('the unit of time could only from {s, m, h, d}')
        exit(1)
44
    time = experiment_config['maxExecDuration'][:-1]
Deshui Yu's avatar
Deshui Yu committed
45
    if not time.isdigit():
46
47
        print_error('time format error!')
        exit(1)
Deshui Yu's avatar
Deshui Yu committed
48
    parse_dict = {'s':1, 'm':60, 'h':3600, 'd':86400}
49
    experiment_config['maxExecDuration'] = int(time) * parse_dict[unit]
Deshui Yu's avatar
Deshui Yu committed
50

51
52
53
54
55
56
57
58
59
def parse_path(experiment_config, config_path):
    '''Parse path in config file'''
    expand_path(experiment_config, 'searchSpacePath')
    if experiment_config.get('trial'):
        expand_path(experiment_config['trial'], 'codeDir')
    if experiment_config.get('tuner'):
        expand_path(experiment_config['tuner'], 'codeDir')
    if experiment_config.get('assessor'):
        expand_path(experiment_config['assessor'], 'codeDir')
QuanluZhang's avatar
QuanluZhang committed
60
61
    if experiment_config.get('advisor'):
        expand_path(experiment_config['advisor'], 'codeDir')
62
63
64
65
66
67
68
69
70
71
72
    
    #if users use relative path, convert it to absolute path
    root_path = os.path.dirname(config_path)
    if experiment_config.get('searchSpacePath'):
        parse_relative_path(root_path, experiment_config, 'searchSpacePath')
    if experiment_config.get('trial'):
        parse_relative_path(root_path, experiment_config['trial'], 'codeDir')
    if experiment_config.get('tuner'):
        parse_relative_path(root_path, experiment_config['tuner'], 'codeDir')
    if experiment_config.get('assessor'):
        parse_relative_path(root_path, experiment_config['assessor'], 'codeDir')
QuanluZhang's avatar
QuanluZhang committed
73
74
    if experiment_config.get('advisor'):
        parse_relative_path(root_path, experiment_config['advisor'], 'codeDir')
75
76
77
78
79
80
81
82
83

def validate_search_space_content(experiment_config):
    '''Validate searchspace content, 
       if the searchspace file is not json format or its values does not contain _type and _value which must be specified, 
       it will not be a valid searchspace file'''
    try:
        search_space_content = json.load(open(experiment_config.get('searchSpacePath'), 'r'))
        for value in search_space_content.values():
            if not value.get('_type') or not value.get('_value'):
84
85
                print_error('please use _type and _value to specify searchspace!')
                exit(1)
86
    except:
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
        print_error('searchspace file is not a valid json format!')
        exit(1)

def validate_kubeflow_operators(experiment_config):
    '''Validate whether the kubeflow operators are valid'''
    if experiment_config.get('kubeflowConfig'):
        if experiment_config.get('kubeflowConfig').get('operator') == 'tf-operator':
            if experiment_config.get('trial').get('master') is not None:
                print_error('kubeflow with tf-operator can not set master')
                exit(1)
        elif experiment_config.get('kubeflowConfig').get('operator') == 'pytorch-operator':
            if experiment_config.get('trial').get('ps') is not None:
                print_error('kubeflow with pytorch-operator can not set ps')
                exit(1)
        
        if experiment_config.get('kubeflowConfig').get('storage') == 'nfs':
            if experiment_config.get('kubeflowConfig').get('nfs') is None:
                print_error('please set nfs configuration!')
                exit(1)
        elif experiment_config.get('kubeflowConfig').get('storage') == 'azureStorage':
            if experiment_config.get('kubeflowConfig').get('azureStorage') is None:
                print_error('please set azureStorage configuration!')
                exit(1)
        elif experiment_config.get('kubeflowConfig').get('storage') is None:
            if experiment_config.get('kubeflowConfig').get('azureStorage'):
                print_error('please set storage type!')
                exit(1)
114

Deshui Yu's avatar
Deshui Yu committed
115
116
def validate_common_content(experiment_config):
    '''Validate whether the common values in experiment_config is valid'''
117
    if not experiment_config.get('trainingServicePlatform') or \
118
        experiment_config.get('trainingServicePlatform') not in ['local', 'remote', 'pai', 'kubeflow']:
119
        print_error('Please set correct trainingServicePlatform!')
120
        exit(1)
121
122
123
    schema_dict = {
            'local': LOCAL_CONFIG_SCHEMA,
            'remote': REMOTE_CONFIG_SCHEMA,
124
125
            'pai': PAI_CONFIG_SCHEMA,
            'kubeflow': KUBEFLOW_CONFIG_SCHEMA
126
        }
127
    try:
128
        schema_dict.get(experiment_config['trainingServicePlatform']).validate(experiment_config)
129
130
131
132
133
        #set default value
        if experiment_config.get('maxExecDuration') is None:
            experiment_config['maxExecDuration'] = '999d'
        if experiment_config.get('maxTrialNum') is None:
            experiment_config['maxTrialNum'] = 99999
SparkSnail's avatar
SparkSnail committed
134
135
136
137
138
        if experiment_config['trainingServicePlatform'] == 'remote':
            for index in range(len(experiment_config['machineList'])):
                if experiment_config['machineList'][index].get('port') is None:
                    experiment_config['machineList'][index]['port'] = 22
                
139
    except Exception as exception:
140
141
        print_error('Your config file is not correct, please check your config file content!\n%s' % exception)
        exit(1)
Deshui Yu's avatar
Deshui Yu committed
142

QuanluZhang's avatar
QuanluZhang committed
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
def validate_customized_file(experiment_config, spec_key):
    '''
    check whether the file of customized tuner/assessor/advisor exists
    spec_key: 'tuner', 'assessor', 'advisor'
    '''
    if experiment_config[spec_key].get('codeDir') and \
        experiment_config[spec_key].get('classFileName') and \
        experiment_config[spec_key].get('className'):
        if not os.path.exists(os.path.join(
                experiment_config[spec_key]['codeDir'],
                experiment_config[spec_key]['classFileName'])):
            print_error('%s file directory is not valid!'%(spec_key))
            exit(1)
    else:
        print_error('%s file directory is not valid!'%(spec_key))
        exit(1)

160
def parse_tuner_content(experiment_config):
Deshui Yu's avatar
Deshui Yu committed
161
    '''Validate whether tuner in experiment_config is valid'''
QuanluZhang's avatar
QuanluZhang committed
162
163
    if experiment_config['tuner'].get('builtinTunerName'):
        experiment_config['tuner']['className'] = experiment_config['tuner']['builtinTunerName']
Deshui Yu's avatar
Deshui Yu committed
164
    else:
QuanluZhang's avatar
QuanluZhang committed
165
        validate_customized_file(experiment_config, 'tuner')
Deshui Yu's avatar
Deshui Yu committed
166

167
def parse_assessor_content(experiment_config):
Deshui Yu's avatar
Deshui Yu committed
168
    '''Validate whether assessor in experiment_config is valid'''
169
    if experiment_config.get('assessor'):
QuanluZhang's avatar
QuanluZhang committed
170
171
        if experiment_config['assessor'].get('builtinAssessorName'):
            experiment_config['assessor']['className'] = experiment_config['assessor']['builtinAssessorName']
172
        else:
QuanluZhang's avatar
QuanluZhang committed
173
            validate_customized_file(experiment_config, 'assessor')
Deshui Yu's avatar
Deshui Yu committed
174

QuanluZhang's avatar
QuanluZhang committed
175
176
177
178
179
180
181
182
183
184
185
186
187
def parse_advisor_content(experiment_config):
    '''Validate whether advisor in experiment_config is valid'''
    if experiment_config['advisor'].get('builtinAdvisorName'):
        experiment_config['advisor']['className'] = experiment_config['advisor']['builtinAdvisorName']
    else:
        validate_customized_file(experiment_config, 'advisor')

def validate_annotation_content(experiment_config, spec_key, builtin_name):
    '''
    Valid whether useAnnotation and searchSpacePath is coexist
    spec_key: 'advisor' or 'tuner'
    builtin_name: 'builtinAdvisorName' or 'builtinTunerName'
    '''
Deshui Yu's avatar
Deshui Yu committed
188
189
    if experiment_config.get('useAnnotation'):
        if experiment_config.get('searchSpacePath'):
190
191
            print_error('If you set useAnnotation=true, please leave searchSpacePath empty')
            exit(1)
Deshui Yu's avatar
Deshui Yu committed
192
193
    else:
        # validate searchSpaceFile
Lee's avatar
Lee committed
194
195
        if experiment_config[spec_key].get(builtin_name) == 'NetworkMorphism':
            return
QuanluZhang's avatar
QuanluZhang committed
196
        if experiment_config[spec_key].get(builtin_name):
197
            if experiment_config.get('searchSpacePath') is None:
198
                print_error('Please set searchSpacePath!')
199
                exit(1)
200
            validate_search_space_content(experiment_config)
Deshui Yu's avatar
Deshui Yu committed
201

202
203
204
def validate_machine_list(experiment_config):
    '''Validate machine list'''
    if experiment_config.get('trainingServicePlatform') == 'remote' and experiment_config.get('machineList') is None:
205
206
        print_error('Please set machineList!')
        exit(1)
Deshui Yu's avatar
Deshui Yu committed
207

208
def validate_all_content(experiment_config, config_path):
Deshui Yu's avatar
Deshui Yu committed
209
    '''Validate whether experiment_config is valid'''
210
    parse_path(experiment_config, config_path)
Deshui Yu's avatar
Deshui Yu committed
211
    validate_common_content(experiment_config)
212
    parse_time(experiment_config)
QuanluZhang's avatar
QuanluZhang committed
213
214
215
216
217
218
219
220
221
    if experiment_config.get('advisor'):
        parse_advisor_content(experiment_config)
        validate_annotation_content(experiment_config, 'advisor', 'builtinAdvisorName')
    else:
        if not experiment_config.get('tuner'):
            raise Exception('Please provide tuner spec!')
        parse_tuner_content(experiment_config)
        parse_assessor_content(experiment_config)
        validate_annotation_content(experiment_config, 'tuner', 'builtinTunerName')