public async Task <IActionResult> Create([FromBody] CreateInputModel model, [FromServices] INodeRepository nodeRepository) { //データの入力チェック 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 (model.ParentId.HasValue) { var parent = await trainingHistoryRepository.GetByIdAsync(model.ParentId.Value); if (parent == null) { return(JsonNotFound($"Training ID {model.ParentId.Value} 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}.")); } } //同じ名前のコンテナは実行できないので、確認する var currentStatus = await clusterManagementLogic.GetContainerStatusAsync(model.Name, CurrentUserInfo.SelectedTenant.Name, false); if (currentStatus.Exist()) { if (currentStatus.IsError()) { return(JsonConflict($"Failed to check cluster status. Please contact your server administrator.")); } return(JsonConflict($"Container {model.Name} already exists: status {currentStatus}")); } 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.")); } } //コンテナの実行前に、推論履歴を作成する(コンテナの実行に失敗した場合、そのステータスをユーザに表示するため) var inferenceHistory = new InferenceHistory() { 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, ModelRepository = model.GitModel.Repository, ModelRepositoryOwner = model.GitModel.Owner, ModelBranch = branch, ModelCommitId = commitId, OptionDic = model.Options ?? new Dictionary <string, string>(), //オプションはnullの可能性があるので、その時は初期化 ParentId = model.ParentId, Memo = model.Memo, Cpu = model.Cpu.Value, Memory = model.Memory.Value, Gpu = model.Gpu.Value, Partition = model.Partition, Status = ContainerStatus.Running.Key }; if (inferenceHistory.OptionDic.ContainsKey("")) //空文字は除外する { inferenceHistory.OptionDic.Remove(""); } inferenceHistoryRepository.Add(inferenceHistory); if (dataSet.IsLocked == false) { dataSet.IsLocked = true; } unitOfWork.Commit(); var result = await clusterManagementLogic.RunInferenceContainerAsync(inferenceHistory); if (result.IsSuccess == false) { //コンテナの起動に失敗した状態。エラーを出力して、保存した推論履歴も削除する。 inferenceHistoryRepository.Delete(inferenceHistory); unitOfWork.Commit(); return(JsonError(HttpStatusCode.ServiceUnavailable, "Failed to run training. The message bellow may be help to resolve: " + result.Error)); } //結果に従い、推論結果を更新する。 //実行には時間がかかりうるので、DBから最新の情報を取ってくる inferenceHistory = await inferenceHistoryRepository.GetByIdAsync(inferenceHistory.Id); inferenceHistory.Configuration = result.Value.Configuration; inferenceHistory.Status = result.Value.Status.Key; unitOfWork.Commit(); if (result.Value.Status.Succeed()) { return(JsonCreated(new InferenceSimpleOutputModel(inferenceHistory))); } 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.")); } //データの存在チェック 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 inferenceHistory = new InferenceHistory() { 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, 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, Status = ContainerStatus.Running.Key, Zip = model.Zip, LocalDataSet = model.LocalDataSet, }; if (inferenceHistory.OptionDic.ContainsKey("")) //空文字は除外する { inferenceHistory.OptionDic.Remove(""); } // 親学習が指定されていれば存在チェック if (model.ParentIds != null) { var maps = new List <InferenceHistoryParentMap>(); 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 = inferenceHistoryRepository.AttachParentAsync(inferenceHistory, parent); if (map != null) { maps.Add(map); } } inferenceHistory.ParentMaps = maps; } // 親推論が指定されていれば存在チェック if (model.InferenceIds != null) { var maps = new List <InferenceHistoryParentInferenceMap>(); foreach (var parentId in model.InferenceIds) { var parentInference = await inferenceHistoryRepository.GetByIdAsync(parentId); if (parentInference == null) { return(JsonNotFound($"Inference ID {parentId} is not found.")); } // 推論履歴に親推論を紐づける var map = inferenceHistoryRepository.AttachParentInferenceToInferenceAsync(inferenceHistory, parentInference); if (map != null) { maps.Add(map); } } inferenceHistory.ParentInferenceMaps = maps; } inferenceHistoryRepository.Add(inferenceHistory); if (dataSet.IsLocked == false) { dataSet.IsLocked = true; } unitOfWork.Commit(); var result = await clusterManagementLogic.RunInferenceContainerAsync(inferenceHistory); if (result.IsSuccess == false) { //コンテナの起動に失敗した状態。エラーを出力して、保存した推論履歴も削除する。 await dataSetLogic.ReleaseLockAsync(inferenceHistory.DataSetId); inferenceHistoryRepository.Delete(inferenceHistory); unitOfWork.Commit(); return(JsonError(HttpStatusCode.ServiceUnavailable, "Failed to run training. The message bellow may be help to resolve: " + result.Error)); } //結果に従い、推論結果を更新する。 //実行には時間がかかりうるので、DBから最新の情報を取ってくる inferenceHistory = await inferenceHistoryRepository.GetByIdAsync(inferenceHistory.Id); inferenceHistory.Configuration = result.Value.Configuration; inferenceHistory.Status = result.Value.Status.Key; unitOfWork.Commit(); if (result.Value.Status.Succeed()) { return(JsonCreated(new InferenceSimpleOutputModel(inferenceHistory))); } else { return(JsonError(HttpStatusCode.ServiceUnavailable, $"Failed to run training. Status={result.Value.Status.Name}. Please contact your server administrator.")); } }