public async Task <IActionResult> Create([FromBody] CreateInputModel model) { // データの入力チェック if (!ModelState.IsValid) { return(JsonBadRequest("Invalid inputs.")); } if (string.IsNullOrWhiteSpace(model.Name)) { // 名前に空文字は許可しない return(JsonBadRequest($"A name of Preprocessing is NOT allowed to set empty string.")); } if (model.GitModel != null && model.GitModel.IsValid() == false) { return(JsonBadRequest($"The input about Git is not valid.")); } // 各リソースの超過チェック Tenant tenant = tenantRepository.Get(CurrentUserInfo.SelectedTenant.Id); string errorMessage = clusterManagementLogic.CheckQuota(tenant, model.Cpu, model.Memory, model.Gpu); if (errorMessage != null) { return(JsonBadRequest(errorMessage)); } Preprocess preprocessing = new Preprocess(); var errorResult = await SetPreprocessDetailsAsync(preprocessing, model); if (errorResult != null) { return(errorResult); } preprocessRepository.Add(preprocessing); unitOfWork.Commit(); return(JsonCreated(new IndexOutputModel(preprocessing))); }
public async Task <IActionResult> Create([FromBody] CreateInputModel model) { //データの入力チェック if (!ModelState.IsValid) { return(JsonBadRequest("Invalid inputs.")); } //データの存在チェック var dataSet = await dataSetRepository.GetByIdAsync(model.DataSetId.Value); if (dataSet == null) { return(JsonNotFound($"DataSet ID {model.DataSetId} is not found.")); } if (string.IsNullOrEmpty(model.Partition) == false) { bool existPartition = await nodeRepository.IsEnablePartitionAsync(model.Partition, true); if (existPartition == false) { return(JsonNotFound($"There are no enable nodes with Partition {model.Partition}.")); } } // 環境変数名のチェック if (model.Options != null && model.Options.Count > 0) { foreach (var env in model.Options) { if (!string.IsNullOrEmpty(env.Key)) { // フォーマットチェック if (!Regex.IsMatch(env.Key, "^[-._a-zA-Z][-._a-zA-Z0-9]*$")) { return(JsonNotFound($"Invalid envName. Please match the format of '^[-._a-zA-Z][-._a-zA-Z0-9]*$'.")); } } } } long? gitId = model.GitModel.GitId ?? CurrentUserInfo.SelectedTenant.DefaultGit?.Id; string branch = model.GitModel.Branch ?? "master"; string commitId = model.GitModel.CommitId; //コミットIDが指定されていなければ、ブランチのHEADからコミットIDを取得する if (string.IsNullOrEmpty(commitId)) { commitId = await gitLogic.GetCommitIdAsync(gitId.Value, model.GitModel.Repository, model.GitModel.Owner, branch); if (string.IsNullOrEmpty(commitId)) { //コミットIDが特定できなかったらエラー return(JsonNotFound($"The branch {branch} for {gitId.Value}/{model.GitModel.Owner}/{model.GitModel.Repository} is not found.")); } } // 各リソースの超過チェック Tenant tenant = tenantRepository.Get(CurrentUserInfo.SelectedTenant.Id); string errorMessage = clusterManagementLogic.CheckQuota(tenant, model.Cpu.Value, model.Memory.Value, model.Gpu.Value); if (errorMessage != null) { return(JsonBadRequest(errorMessage)); } //コンテナの実行前に、学習履歴を作成する(コンテナの実行に失敗した場合、そのステータスをユーザに表示するため) var trainingHistory = new TrainingHistory() { Name = model.Name, DisplayId = -1, ContainerRegistryId = model.ContainerImage.RegistryId ?? CurrentUserInfo.SelectedTenant.DefaultRegistry?.Id, ContainerImage = model.ContainerImage.Image, ContainerTag = model.ContainerImage.Tag, //latestは運用上使用されていないハズなので、そのまま直接代入 DataSetId = model.DataSetId.Value, EntryPoint = model.EntryPoint, ModelGitId = gitId.Value, ModelRepository = model.GitModel.Repository, ModelRepositoryOwner = model.GitModel.Owner, ModelBranch = branch, ModelCommitId = commitId, OptionDic = model.Options ?? new Dictionary <string, string>(), //オプションはnullの可能性があるので、その時は初期化 Memo = model.Memo, Cpu = model.Cpu.Value, Memory = model.Memory.Value, Gpu = model.Gpu.Value, Partition = model.Partition, PortList = model.Ports, Status = ContainerStatus.Running.Key, Zip = model.Zip, LocalDataSet = model.LocalDataSet, }; if (trainingHistory.OptionDic.ContainsKey("")) //空文字は除外する { trainingHistory.OptionDic.Remove(""); } // 親学習が指定されていれば存在チェック if (model.ParentIds != null) { var maps = new List <TrainingHistoryParentMap>(); foreach (var parentId in model.ParentIds) { var parent = await trainingHistoryRepository.GetByIdAsync(parentId); if (parent == null) { return(JsonNotFound($"Training ID {parentId} is not found.")); } // 学習履歴に親学習を紐づける var map = trainingHistoryRepository.AttachParentAsync(trainingHistory, parent); if (map != null) { maps.Add(map); } } trainingHistory.ParentMaps = maps; } //タグの登録 if (model.Tags != null && model.Tags.Count() > 0) { tagLogic.CreateTrainingHistoryTags(trainingHistory, model.Tags); } trainingHistoryRepository.Add(trainingHistory); if (dataSet.IsLocked == false) { dataSet.IsLocked = true; } unitOfWork.Commit(); var result = await clusterManagementLogic.RunTrainContainerAsync(trainingHistory); if (result.IsSuccess == false) { //コンテナの起動に失敗した状態。エラーを出力して、保存した学習履歴も削除する。 trainingHistoryRepository.Delete(trainingHistory); unitOfWork.Commit(); return(JsonError(HttpStatusCode.ServiceUnavailable, "Failed to run training. The message bellow may be help to resolve: " + result.Error)); } //結果に従い、学習結果を更新する。 //実行には時間がかかりうるので、DBから最新の情報を取ってくる trainingHistory = await trainingHistoryRepository.GetByIdAsync(trainingHistory.Id); trainingHistory.Configuration = result.Value.Configuration; trainingHistory.Status = result.Value.Status.Key; unitOfWork.Commit(); if (result.Value.Status.Succeed()) { return(JsonCreated(new SimpleOutputModel(trainingHistory))); } else { return(JsonError(HttpStatusCode.ServiceUnavailable, $"Failed to run training. Status={result.Value.Status.Name}. Please contact your server administrator.")); } }
public async Task <IActionResult> Create([FromBody] CreateInputModel model) { //データの入力チェック if (!ModelState.IsValid) { return(JsonBadRequest("Invalid inputs.")); } //データセットが指定されていれば存在チェック if (model.DataSetId.HasValue) { var dataSet = await dataSetRepository.GetByIdAsync(model.DataSetId.Value); if (dataSet == null) { return(JsonNotFound($"DataSet ID {model.DataSetId} is not found.")); } } // ノートブック無期限フラグのチェック Tenant tenant = tenantRepository.Get(CurrentUserInfo.SelectedTenant.Id); if (tenant.AvailableInfiniteTimeNotebook == false && model.ExpiresIn == 0) { return(JsonBadRequest($"Tenant [{tenant.DisplayName}] is not allowed to run infinite time.")); } if (string.IsNullOrEmpty(model.Partition) == false) { bool existPartition = await nodeRepository.IsEnablePartitionAsync(model.Partition, true); if (existPartition == false) { return(JsonNotFound($"There are no enable nodes with Partition {model.Partition}.")); } } // 環境変数名のチェック if (model.Options != null && model.Options.Count > 0) { foreach (var env in model.Options) { if (!string.IsNullOrEmpty(env.Key)) { // フォーマットチェック if (!Regex.IsMatch(env.Key, "^[-._a-zA-Z][-._a-zA-Z0-9]*$")) { return(JsonNotFound($"Invalid envName. Please match the format of '^[-._a-zA-Z][-._a-zA-Z0-9]*$'.")); } } } } // 各リソースの超過チェック string errorMessage = clusterManagementLogic.CheckQuota(tenant, model.Cpu.Value, model.Memory.Value, model.Gpu.Value); if (errorMessage != null) { return(JsonBadRequest(errorMessage)); } //コンテナの実行前に、ノートブック履歴を作成する(コンテナの実行に失敗した場合、そのステータスをユーザに表示するため) var notebookHistory = new NotebookHistory() { DisplayId = -1, Name = model.Name, DataSetId = model.DataSetId, OptionDic = model.Options ?? new Dictionary <string, string>(), //オプションはnullの可能性があるので、その時は初期化 Cpu = model.Cpu.Value, Memory = model.Memory.Value, Gpu = model.Gpu.Value, Partition = model.Partition, Memo = model.Memo, Status = ContainerStatus.Running.Key, StartedAt = DateTime.Now, ExpiresIn = model.ExpiresIn, LocalDataSet = model.LocalDataSet, EntryPoint = model.EntryPoint, JupyterLabVersion = model.JupyterLabVersion }; //コンテナが指定されているかチェック if (model.ContainerImage != null) { notebookHistory.ContainerRegistryId = model.ContainerImage.RegistryId ?? CurrentUserInfo.SelectedTenant.DefaultRegistry?.Id; notebookHistory.ContainerImage = model.ContainerImage.Image; notebookHistory.ContainerTag = model.ContainerImage.Tag; //latestは運用上使用されていないハズなので、そのまま直接代入 } else { //コンテナイメージの設定がない場合デフォルトのイメージを設定 notebookHistory.ContainerRegistryId = null; notebookHistory.ContainerImage = "kamonohashi/jupyterlab"; notebookHistory.ContainerTag = "tensorflow-2.2.0"; } //gitが指定されているかチェック if (model.GitModel != null) { //gitリポジトリ名が指定されていれば、ブランチ、コミットIDを設定。指定されていなければnull long? gitId = model.GitModel.GitId ?? CurrentUserInfo.SelectedTenant.DefaultGit?.Id; string branch = null; string commitId = null; if (!string.IsNullOrEmpty(model.GitModel.Repository)) { branch = model.GitModel.Branch ?? "master"; commitId = model.GitModel.CommitId; //コミットIDが指定されていなければ、ブランチのHEADからコミットIDを取得する if (string.IsNullOrEmpty(commitId)) { commitId = await gitLogic.GetCommitIdAsync(gitId.Value, model.GitModel.Repository, model.GitModel.Owner, branch); if (string.IsNullOrEmpty(commitId)) { //コミットIDが特定できなかったらエラー return(JsonNotFound($"The branch {branch} for {gitId.Value}/{model.GitModel.Owner}/{model.GitModel.Repository} is not found.")); } } } //git情報を設定 notebookHistory.ModelGitId = gitId.Value; notebookHistory.ModelRepository = model.GitModel.Repository; notebookHistory.ModelRepositoryOwner = model.GitModel.Owner; notebookHistory.ModelBranch = branch; notebookHistory.ModelCommitId = commitId; } // JupyterLabのバージョンが指定されているかチェック if (string.IsNullOrEmpty(notebookHistory.JupyterLabVersion)) { // null または 空文字 の場合はデフォルトのバージョンを指定 notebookHistory.JupyterLabVersion = "2.3.1"; } if (notebookHistory.OptionDic.ContainsKey("")) //空文字は除外する { notebookHistory.OptionDic.Remove(""); } // 親学習が指定されていれば存在チェック if (model.ParentIds != null) { var maps = new List <NotebookHistoryParentTrainingMap>(); foreach (var parentId in model.ParentIds) { var parent = await trainingHistoryRepository.GetByIdAsync(parentId); if (parent == null) { return(JsonNotFound($"Training ID {parentId} is not found.")); } // ノートブック履歴に親学習を紐づける var map = notebookHistoryRepository.AttachParentToNotebookAsync(notebookHistory, parent); if (map != null) { maps.Add(map); } } notebookHistory.ParentTrainingMaps = maps; } // 親推論が指定されていれば存在チェック if (model.InferenceIds != null) { var maps = new List <NotebookHistoryParentInferenceMap>(); foreach (var parentId in model.InferenceIds) { var parenInferencet = await inferenceHistoryRepository.GetByIdAsync(parentId); if (parenInferencet == null) { return(JsonNotFound($"Inference ID {parentId} is not found.")); } // ノートブック履歴に親学習を紐づける var map = notebookHistoryRepository.AttachParentInferenceToNotebookAsync(notebookHistory, parenInferencet); if (map != null) { maps.Add(map); } } notebookHistory.ParentInferenceMaps = maps; } notebookHistoryRepository.Add(notebookHistory); unitOfWork.Commit(); var result = await clusterManagementLogic.RunNotebookContainerAsync(notebookHistory); if (result.IsSuccess == false) { //コンテナの起動に失敗した状態。エラーを出力して、保存したノートブック履歴も削除する。 notebookHistoryRepository.Delete(notebookHistory); unitOfWork.Commit(); return(JsonError(HttpStatusCode.ServiceUnavailable, "Failed to run notebook. The message bellow may be help to resolve: " + result.Error)); } //結果に従い、ノートブック結果を更新する。 //実行には時間がかかりうるので、DBから最新の情報を取ってくる notebookHistory = await notebookHistoryRepository.GetByIdAsync(notebookHistory.Id); notebookHistory.Configuration = result.Value.Configuration; notebookHistory.Status = result.Value.Status.Key; unitOfWork.Commit(); if (result.Value.Status.Succeed()) { return(JsonCreated(new SimpleOutputModel(notebookHistory))); } else { return(JsonError(HttpStatusCode.ServiceUnavailable, $"Failed to run notebook. Status={result.Value.Status.Name}. Please contact your server administrator.")); } }