Пример #1
0
 def install_deps(self, args):
     package_name = args.package_name
     requirements = args.requirements
     upgrade = args.upgrade
     force_reinstall = args.force_reinstall
     pkgs = ' '.join(package_name)
     config_path = self.get_model_config_path()
     config = get_config_parser(config_path)
     section_name = DEFAULT_MODEL_SECTION
     model_id = config_get(config.get, section_name, 'model_id')
     runtime = config_get(config.get, section_name, 'runtime')
     client = self._get_docker_client()
     command = ['pip install', '--cache-dir', '/tmp/.cache/']
     if upgrade:
         command.append('--upgrade')
     if force_reinstall:
         command.append('--force-reinstall')
     deps = []
     if pkgs:
         deps.append(pkgs)
     if requirements:
         deps.append('-r {}'.format(requirements))
     command.append('-t /code/lib {}'.format(' '.join(deps)))
     command = ' '.join(command)
     image_name = RUNTIMES[runtime]
     self._get_or_pull_image(client, image_name)
     with console.status('开始安装模型依赖包...', spinner='earth'):
         command = ('sh -c "{}"').format(command)
         container_name = generate_container_name(model_id)
         self._force_remove_container(client, container_name)
         self._run_by_container(client, image_name, command, container_name)
         output('[green]安装完成[/green]')
Пример #2
0
 def upload_model_expfs(self, args):
     home = get_home()
     project = get_active_project()
     config_path = self.get_model_config_path()
     config = get_config_parser(config_path)
     section_name = DEFAULT_MODEL_SECTION
     model_id = config_get(config.get, section_name, 'model_id')
     oauth2_section = DEFAULT_OAUTH2_SECTION
     token_section = DEFAULT_TOKEN_SECTION
     config = read_config(project)
     access_token = config_get(config.get, token_section, 'access_token')
     endpoint = config_get(config.get, oauth2_section, 'endpoint')
     api = API(access_token,
               endpoint=endpoint,
               timeout=DEFAULT_MODEL_TIMEOUT)
     try:
         result = api.upload_model_expfs(model_id, 'uploadtest.zip')
     except APIError as e:
         output('[red]上传模型扩展集失败:[/red]')
         output_json(e.result)
         sys.exit(1)
     task_id = result.task_id
     output('上传模型扩展集任务:{}'.format(task_id))
     task_path = join(home, '.bge', 'expfs.task_id')
     with open(task_path, 'w') as f:
         f.write(task_id)
     output('上传模型扩展集任务返回结果:')
     progress = self._wait_model_task(api, task_id, task_path)
     if 'SUCCESS' == progress:
         output('[green]模型 {} 上传模型扩展集成功。'.format(model_id))
     elif 'FAILURE' == progress:
         output('[red]模型 {} 上传模型扩展集失败。'.format(model_id))
     elif 'REVOKED' == progress:
         output('[white]模型 {} 上传模型扩展集任务已被撤销。'.format(model_id))
Пример #3
0
 def _new_project(self, config_path):
     config_parser = get_config_parser(config_path)
     oauth2_section = constants.DEFAULT_OAUTH2_SECTION
     if oauth2_section not in config_parser.sections():
         config_parser.add_section(oauth2_section)
     for key, conf in constants.CLIENT_CREDENTIALS_CONFIGS:
         type_ = conf['type']
         saved_value = self._get_config_value(config_parser, key, type_)
         secure = conf.get('secure')
         description = conf.get('description', '')
         value = saved_value or conf.get('default', '')
         show_value = value
         if secure and value:
             show_value = secure_str(value)
         input_value = Prompt.ask(
             '请输入{} {} ([bold cyan]{}[/bold cyan])'.format(
                 description, key, show_value
             ),
             show_default=False,
             default=value
         )
         if input_value:
             config_parser.set(oauth2_section, key, input_value)
         elif saved_value is None:
             if conf.get('default') is not None:
                 config_parser.set(
                     oauth2_section, key, conf.get('default'))
             else:
                 config_parser.set(oauth2_section, key, '')
     with open(config_path, 'w') as config_file:
         config_parser.write(config_file)
     output('')
     output('[green]配置已保存至:[/green]{}'.format(config_path))
Пример #4
0
 def config_model(self, args):
     if args.show:
         return self._read_model_project(args)
     config_path = self.get_model_config_path()
     config_parser = get_config_parser(config_path)
     model_id, runtime, memory_size, timeout \
         = self._config_model(config_parser)
     self._save_model_config(model_id, runtime, memory_size, timeout)
Пример #5
0
 def run_model(self, args):
     params = {}
     if args.file:
         filepath = args.file
         if not exists(filepath):
             output('文件不存在:{}'.format(filepath))
             sys.exit(1)
         if isdir(filepath):
             output('存在文件夹:{}'.format(filepath))
             sys.exit(1)
         with open(filepath, 'r') as fp:
             params = json.load(fp)
     elif args.args:
         params = dict(args.args)
     draft = args.draft
     test = args.test
     project = get_active_project()
     config_path = self.get_model_config_path()
     config = get_config_parser(config_path)
     section_name = DEFAULT_MODEL_SECTION
     model_id = config_get(config.get, section_name, 'model_id')
     oauth2_section = DEFAULT_OAUTH2_SECTION
     token_section = DEFAULT_TOKEN_SECTION
     config = read_config(project)
     access_token = config_get(config.get, token_section, 'access_token')
     endpoint = config_get(config.get, oauth2_section, 'endpoint')
     api = API(access_token,
               endpoint=endpoint,
               timeout=DEFAULT_MODEL_TIMEOUT)
     try:
         if draft is True:
             result = api.invoke_draft_model(model_id, **params)
         elif test is True:
             port = args.port
             api = API(access_token,
                       endpoint='{}:{}'.format(TEST_SERVER_ENDPOINT, port),
                       timeout=DEFAULT_MODEL_TIMEOUT)
             result = api.invoke_model(model_id, **params)
         else:
             result = api.invoke_model(model_id, **params)
     except APIError as e:
         output('[red]模型运行失败:[/red]')
         output_json(e.result)
         sys.exit(1)
     output('[green]模型返回值:[/green]')
     output_json(result.json())
Пример #6
0
 def _write_token_config(self, project, token_result):
     access_token = token_result['access_token']
     token_type = token_result['token_type']
     expires_in = str(token_result['expires_in'])
     scope = token_result['scope']
     config_path = get_config_path(project)
     config_parser = get_config_parser(config_path)
     section_name = constants.DEFAULT_TOKEN_SECTION
     if section_name not in config_parser.sections():
         config_parser.add_section(section_name)
     config_parser.set(section_name, 'access_token', access_token)
     config_parser.set(section_name, 'token_type', token_type)
     config_parser.set(section_name, 'expires_in', expires_in)
     config_parser.set(section_name, 'scope', scope)
     with open(config_path, 'w') as config_file:
         config_parser.write(config_file)
     output('[green]令牌已保存至:[/green]{}'.format(config_path))
Пример #7
0
 def _install_sdk(self):
     with console.status("正在安装 bge-python-sdk", spinner="earth"):
         config_path = self.get_model_config_path()
         config = get_config_parser(config_path)
         section_name = DEFAULT_MODEL_SECTION
         model_id = config_get(config.get, section_name, 'model_id')
         runtime = config_get(config.get, section_name, 'runtime')
         client = self._get_docker_client()
         command = ('pip install --cache-dir /tmp/.cache/ --no-deps '
                    'bge-python-sdk pimento requests_toolbelt -t /code/lib')
         image_name = RUNTIMES[runtime]
         self._get_or_pull_image(client, image_name)
         output('开始安装模型依赖包...')
         command = ('sh -c "{}"').format(command)
         container_name = generate_container_name(model_id)
         self._force_remove_container(client, container_name)
         self._run_by_container(client, image_name, command, container_name)
         output('[green]安装完成[/green]')
Пример #8
0
 def start_model(self, args):
     port = args.port
     home = get_home()
     config_path = self.get_model_config_path()
     config = get_config_parser(config_path)
     section_name = DEFAULT_MODEL_SECTION
     model_id = config_get(config.get, section_name, 'model_id')
     runtime = config_get(config.get, section_name, 'runtime')
     client = self._get_docker_client()
     image_name = RUNTIMES[runtime]
     self._get_or_pull_image(client, image_name)
     command = 'python -u /server/app.py'
     user = get_sys_user()
     container_name = generate_container_name(model_id)
     self._force_remove_container(client, container_name)
     container = client.containers.run(
         image_name,
         command=command,
         name=container_name,
         volumes={home: {
             'bind': WORKDIR,
             'mode': 'rw'
         }},
         stop_signal='SIGINT',
         ports={TEST_SERVER_PORT: port},
         user=user,
         detach=True,
         stream=True,
         auto_remove=True)
     output('Model debug server is starting at {}...'.format(port))
     output('Model {} was registered'.format(model_id))
     output('\n\tURL: {}:{}/model/{}'.format(TEST_SERVER_ENDPOINT, port,
                                             model_id))
     output('\tMethod: GET\n')
     try:
         logs = container.logs(stream=True, follow=True)
         for log in logs:
             output(log.strip().decode('utf-8'))
     finally:
         if container.status != 'exited':
             try:
                 container.remove(force=True)
             except Exception:
                 pass
Пример #9
0
 def model_versions(self, args):
     limit = args.limit
     next_page = args.next_page
     project = get_active_project()
     config_path = self.get_model_config_path()
     config = get_config_parser(config_path)
     section_name = DEFAULT_MODEL_SECTION
     model_id = config_get(config.get, section_name, 'model_id')
     oauth2_section = DEFAULT_OAUTH2_SECTION
     token_section = DEFAULT_TOKEN_SECTION
     config = read_config(project)
     access_token = config_get(config.get, token_section, 'access_token')
     endpoint = config_get(config.get, oauth2_section, 'endpoint')
     api = API(access_token,
               endpoint=endpoint,
               timeout=DEFAULT_MODEL_TIMEOUT)
     try:
         result = api.model_versions(model_id,
                                     limit=limit,
                                     next_page=next_page)
     except APIError as e:
         output('[red]获取模型版本列表失败:[/red]')
         output_json(e.result)
         sys.exit(1)
     output('第 {} 页,模型 {} 已发布版本:'.format(next_page or 1, model_id))
     output('...')
     length = None
     items = result['result']
     for item in items:
         version = item['version']
         message = item['message']
         create_time = datetime.fromtimestamp(item['create_time'])
         if length is None:
             length = len(str(version))
         output('发布时间:{},版本号:{},发布记录:{}'.format(create_time,
                                                str(version).rjust(length),
                                                message))
     output('...')
     size = len(items)
     if size == 0 or size < limit or next_page == result['next_page']:
         output('下一页:无')
     else:
         output('下一页:{}'.format(result['next_page']))
Пример #10
0
 def handler(self, args):
     project = get_active_project()
     config_path = get_config_path(project)
     config_parser = get_config_parser(config_path)
     oauth2_section = constants.DEFAULT_OAUTH2_SECTION
     client_id = config_get(config_parser.get, oauth2_section, 'client_id')
     client_secret = config_get(config_parser.get, oauth2_section,
                                'client_secret')
     endpoint = config_get(config_parser.get, oauth2_section, 'endpoint')
     redirect_uri = args.redirect_uri
     oauth2 = OAuth2(client_id,
                     client_secret,
                     endpoint=endpoint,
                     timeout=60.)
     authorization_url = oauth2.get_authorization_url(redirect_uri,
                                                      state=args.state,
                                                      scopes=args.scopes)
     output('授权页面地址为:{}'.format(authorization_url))
     output('浏览器启动中...')
     webbrowser.open(authorization_url, new=1, autoraise=False)
     output('请在浏览器登录并完成授权,复制跳转后页面链接的 code 参数并关闭浏览器。\n')
     while True:
         code = Prompt.ask('请输入浏览器回调地址携带的参数 [cyan]code[/cyan]')
         code = code.strip()
         if code:
             break
         output('[red]参数 code 不能为空[/red]')
     try:
         token_result = oauth2.exchange_authorization_code(
             code, redirect_uri=redirect_uri)
     except APIError as e:
         output('[red]令牌获取出错:[/red]')
         output_json(e.result)
         sys.exit(1)
     self._write_token_config(project, token_result)
     output('[green]令牌内容如下[/green]')
     content = []
     for key in [
             'access_token', 'token_type', 'expires_in', 'scope',
             'refresh_token'
     ]:
         content.append('{} = {}'.format(key, token_result[key]))
     output_syntax('\n'.join(content), lexer='INI')
Пример #11
0
 def _save_model_config(self,
                        model_id,
                        runtime,
                        memory_size,
                        timeout,
                        home=None):
     # save
     config_path = self.get_model_config_path(home=home)
     config = get_config_parser(config_path)
     section_name = DEFAULT_MODEL_SECTION
     if section_name not in config.sections():
         config.add_section(section_name)
     output('开始保存解读模型配置...')
     output('配置文件 {}'.format(config_path))
     config.set(section_name, 'model_id', model_id)
     config.set(section_name, 'runtime', runtime)
     config.set(section_name, 'memory_size', str(memory_size))
     config.set(section_name, 'timeout', str(timeout))
     with open(config_path, 'w') as config_file:
         config.write(config_file)
     output('')
     output('[green]解读模型配置已保存至[/green] {}'.format(config_path))
Пример #12
0
 def handler(self, args):
     project = get_active_project()
     config_path = get_config_path(project)
     config_parser = get_config_parser(config_path)
     oauth2_section = constants.DEFAULT_OAUTH2_SECTION
     client_id = config_get(config_parser.get, oauth2_section, 'client_id')
     client_secret = config_get(
         config_parser.get, oauth2_section, 'client_secret')
     endpoint = config_get(config_parser.get, oauth2_section, 'endpoint')
     oauth2 = OAuth2(
         client_id, client_secret, endpoint=endpoint, timeout=60.)
     try:
         token_result = oauth2.get_credentials_token()
     except APIError as e:
         output('[red]令牌获取出错:[/red]')
         output_json(e.result)
         sys.exit(1)
     self._write_token_config(project, token_result)
     console.rule('[green]令牌内容如下[/green]')
     content = []
     for key in ['access_token', 'token_type', 'expires_in', 'scope']:
         content.append('{} = {}'.format(key, token_result[key]))
     output_syntax('\n'.join(content), lexer='INI')
Пример #13
0
 def rollback_model(self, args):
     version = args.version
     home = get_home()
     project = get_active_project()
     config_path = self.get_model_config_path()
     config = get_config_parser(config_path)
     section_name = DEFAULT_MODEL_SECTION
     model_id = config_get(config.get, section_name, 'model_id')
     oauth2_section = DEFAULT_OAUTH2_SECTION
     token_section = DEFAULT_TOKEN_SECTION
     config = read_config(project)
     access_token = config_get(config.get, token_section, 'access_token')
     endpoint = config_get(config.get, oauth2_section, 'endpoint')
     api = API(access_token,
               endpoint=endpoint,
               timeout=DEFAULT_MODEL_TIMEOUT)
     try:
         result = api.rollback_model(model_id, version)
     except APIError as e:
         output('[red]模型回滚失败:[/red]')
         output_json(e.result)
         sys.exit(1)
     task_id = result.task_id
     output('模型回滚任务:{}'.format(task_id))
     task_path = join(home, '.bge', 'task_id')
     with open(task_path, 'w') as f:
         f.write(task_id)
     progress = self._wait_model_task(api, task_id, task_path)
     if 'SUCCESS' == progress:
         output('[green]模型 {} 灰度版已成功回滚至版本 {}。[/green]'.format(
             model_id, version))
     elif 'FAILURE' == progress:
         output('[red]模型 {} 灰度回滚至版本 {} 失败。任务结果:{}[/red]'.format(
             model_id, version, result))
     elif 'REVOKED' == progress:
         output('[white]模型 {} 灰度回滚至版本 {} 任务已被撤销失败。[/white]'.format(
             model_id, version))
Пример #14
0
 def publish_model(self, args):
     """发布模型到稳定版"""
     message = args.message
     project = get_active_project()
     config_path = self.get_model_config_path()
     config = get_config_parser(config_path)
     section_name = DEFAULT_MODEL_SECTION
     model_id = config_get(config.get, section_name, 'model_id')
     oauth2_section = DEFAULT_OAUTH2_SECTION
     token_section = DEFAULT_TOKEN_SECTION
     config = read_config(project)
     access_token = config_get(config.get, token_section, 'access_token')
     endpoint = config_get(config.get, oauth2_section, 'endpoint')
     api = API(access_token,
               endpoint=endpoint,
               timeout=DEFAULT_MODEL_TIMEOUT)
     try:
         result = api.publish_model(model_id, message)
     except APIError as e:
         output('[red]模型发布失败:[/red]')
         output_json(e.result)
         sys.exit(1)
     output('[green]模型 {} 稳定版已成功发布。\n版本号:{}。[/green]'.format(
         model_id, result['version']))
Пример #15
0
 def deploy_model(self, args):
     """部署模型"""
     ignore_source = args.ignore_source
     home = get_home()
     project = get_active_project()
     config_path = self.get_model_config_path()
     config = get_config_parser(config_path)
     section_name = DEFAULT_MODEL_SECTION
     model_id = config_get(config.get, section_name, 'model_id')
     timestr = datetime.now().strftime('%Y%m%d%H%M%S%f')
     randstr = uuid4().hex
     zip_filename = '{}.{}.{}.zip'.format(model_id, timestr, randstr)
     params = {}
     params['runtime'] = config_get(config.get, section_name, 'runtime')
     params['memory_size'] = config_get(config.getint, section_name,
                                        'memory_size')
     params['timeout'] = config_get(config.getint, section_name, 'timeout')
     oauth2_section = DEFAULT_OAUTH2_SECTION
     token_section = DEFAULT_TOKEN_SECTION
     config = read_config(project)
     access_token = config_get(config.get, token_section, 'access_token')
     endpoint = config_get(config.get, oauth2_section, 'endpoint')
     api = API(access_token,
               endpoint=endpoint,
               timeout=DEFAULT_MODEL_TIMEOUT)
     object_name = None
     if not ignore_source:
         ignore_path = join(home, BGE_IGNORE_FILE)
         if not exists(ignore_path):
             output('未发现 .bgeignore 文件,初始化 {} ...'.format(ignore_path))
             open(ignore_path, 'w').write(BGEIGNORE_TEMPLATE)
         minify_path = join(home, BGE_MINIFY_FILE)
         if not exists(minify_path):
             output('未发现 .bgeminify 文件,初始化 {} ...'.format(minify_path))
             open(minify_path, 'w').write(BGEMINIFY_TEMPLATE)
         output('开始打包模型源码...')
         zip_tmpdir = join(home, '.bge', 'tmp')
         if not exists(zip_tmpdir):
             os.makedirs(zip_tmpdir)
         with tempfile.NamedTemporaryFile(suffix='.zip',
                                          prefix='model-',
                                          dir=zip_tmpdir,
                                          delete=False) as tmp:
             with zipfile.ZipFile(tmp.name, 'w', ZIP_COMPRESSION) as zf:
                 self._zip_codedir(home, zf)
             tmp.flush()
             tmp.seek(0, 2)
             size = tmp.tell()
             tmp.seek(0)
             human_size = human_byte(size)
             if size > 100 * 1024 * 1024:
                 output('打包后 zip 文件大小为 {},最大限制 100MB'.format(human_size))
                 exit(1)
             output('打包成功:{}'.format(tmp.name))
             output('文件大小:{}'.format(human_size))
             output('开始上传模型源码...')
             try:
                 object_name = api.upload(zip_filename, tmp)
             except APIError as e:
                 output('[red]上传模型源码失败:[/red]')
                 output_json(e.result)
                 sys.exit(1)
             output('[green]上传成功[green]')
     with console.status('模型部署中...', spinner='earth'):
         try:
             result = api.deploy_model(model_id,
                                       object_name=object_name,
                                       **params)
         except APIError as e:
             output('[red]部署模型失败:[/red]')
             output_json(e.result)
             sys.exit(1)
     task_id = result.task_id
     output('模型部署任务:{}'.format(task_id))
     task_path = join(home, '.bge', 'task_id')
     with open(task_path, 'w') as f:
         f.write(task_id)
     output('模型部署任务返回结果:')
     progress = self._wait_model_task(api, task_id, task_path)
     if 'SUCCESS' == progress:
         output('[green]模型 {} 灰度部署成功。'.format(model_id))
     elif 'FAILURE' == progress:
         output('[red]模型 {} 灰度部署失败。任务结果:{}'.format(model_id, result))
     elif 'REVOKED' == progress:
         output('[white]模型 {} 灰度部署任务已被撤销。'.format(model_id))