public async Task <IActionResult> Rerun(long?id, [FromBody] RerunInputModel model, [FromServices] INodeRepository nodeRepository)
        {
            //データの入力チェック
            if (!ModelState.IsValid)
            {
                return(JsonBadRequest("Invalid inputs."));
            }
            //データの存在チェック
            var notebookHistory = await notebookHistoryRepository.GetIncludeAllAsync(id.Value);

            if (notebookHistory == null)
            {
                return(JsonNotFound($"Notebook ID {id} is not found."));
            }
            //ステータスのチェック
            if (notebookHistory.GetStatus().Exist())
            {
                return(JsonNotFound($"Notebook ID {id} is already running."));
            }

            //データセットが指定されていれば存在チェック
            if (model.DataSetId.HasValue)
            {
                var dataSet = await dataSetRepository.GetByIdAsync(model.DataSetId.Value);

                if (dataSet == null)
                {
                    return(JsonNotFound($"DataSet ID {model.DataSetId} is not found."));
                }
            }
            if (string.IsNullOrEmpty(notebookHistory.Partition) == false)
            {
                bool existPartition = await nodeRepository.IsEnablePartitionAsync(notebookHistory.Partition, true);

                if (existPartition == false)
                {
                    return(JsonNotFound($"There are no enable nodes with Partition {notebookHistory.Partition}."));
                }
            }

            if (notebookHistory.ModelGitId != null)
            {
                //gitリポジトリ名が指定されていれば、ブランチ、コミットIDを設定。指定されていなければnull
                long?  gitId    = notebookHistory.ModelGitId ?? CurrentUserInfo.SelectedTenant.DefaultGit?.Id;
                string branch   = null;
                string commitId = null;
                if (!string.IsNullOrEmpty(notebookHistory.ModelRepository))
                {
                    branch   = notebookHistory.ModelBranch ?? "master";
                    commitId = notebookHistory.ModelCommitId;
                    //コミットIDが指定されていなければ、ブランチのHEADからコミットIDを取得する
                    if (string.IsNullOrEmpty(commitId))
                    {
                        commitId = await gitLogic.GetCommitIdAsync(gitId.Value, notebookHistory.ModelRepository, notebookHistory.ModelRepositoryOwner, branch);

                        if (string.IsNullOrEmpty(commitId))
                        {
                            //コミットIDが特定できなかったらエラー
                            return(JsonNotFound($"The branch {branch} for {gitId.Value}/{notebookHistory.ModelRepositoryOwner}/{notebookHistory.ModelRepository} is not found."));
                        }
                    }
                }
            }

            // 現状のノートブック履歴IDに紐づいている親学習をすべて外す。
            notebookHistoryRepository.DetachParentToNotebookAsync(notebookHistory);

            // 親学習が指定されていれば存在チェック
            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;
            }

            //コンテナの実行前に、ノートブック履歴を更新する(コンテナの実行に失敗した場合、そのステータスをユーザに表示するため)
            notebookHistory.DataSetId   = model.DataSetId;
            notebookHistory.Cpu         = model.Cpu.Value;
            notebookHistory.Memory      = model.Memory.Value;
            notebookHistory.Gpu         = model.Gpu.Value;
            notebookHistory.Status      = ContainerStatus.Running.Key;
            notebookHistory.StartedAt   = DateTime.Now;
            notebookHistory.CompletedAt = null;
            notebookHistory.ExpiresIn   = model.ExpiresIn;

            notebookHistoryRepository.Update(notebookHistory);
            unitOfWork.Commit();

            var result = await clusterManagementLogic.RunNotebookContainerAsync(notebookHistory); // TODO:暫定的に親学習はnull

            if (result.IsSuccess == false)
            {
                //コンテナの起動に失敗した状態。エラーを出力して、保存したノートブック履歴も削除する。
                notebookHistory.Status      = ContainerStatus.Killed.Key;
                notebookHistory.CompletedAt = DateTime.Now;
                notebookHistoryRepository.Update(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."));
            }
        }
Exemple #2
0
        public async Task <IActionResult> Rerun(long?id, [FromBody] RerunInputModel model)
        {
            // データの入力チェック
            if (!ModelState.IsValid)
            {
                return(JsonBadRequest("Invalid inputs."));
            }
            // データの存在チェック
            var notebookHistory = await notebookHistoryRepository.GetIncludeAllAsync(id.Value);

            if (notebookHistory == null)
            {
                return(JsonNotFound($"Notebook ID {id} is not found."));
            }
            // ステータスのチェック
            if (notebookHistory.GetStatus().Exist())
            {
                return(JsonNotFound($"Notebook ID {id} is already running."));
            }

            // データセットが指定されていれば存在チェック
            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(notebookHistory.Partition) == false)
            {
                bool existPartition = await nodeRepository.IsEnablePartitionAsync(notebookHistory.Partition, true);

                if (existPartition == false)
                {
                    return(JsonNotFound($"There are no enable nodes with Partition {notebookHistory.Partition}."));
                }
            }

            // コンテナが指定されているかチェック
            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;
            }
            else
            {
                // gitが未指定の場合は各項目にnullを設定する
                notebookHistory.ModelGitId           = null;
                notebookHistory.ModelRepository      = null;
                notebookHistory.ModelRepositoryOwner = null;
                notebookHistory.ModelBranch          = null;
                notebookHistory.ModelCommitId        = null;
            }

            // JupyterLabのバージョンが指定されているかチェック
            if (string.IsNullOrEmpty(model.JupyterLabVersion))
            {
                // null または 空文字 の場合はデフォルトのバージョンを指定
                notebookHistory.JupyterLabVersion = "2.3.1";
            }
            else
            {
                notebookHistory.JupyterLabVersion = model.JupyterLabVersion;
            }

            // 各リソースの超過チェック
            string errorMessage = clusterManagementLogic.CheckQuota(tenant, model.Cpu.Value, model.Memory.Value, model.Gpu.Value);

            if (errorMessage != null)
            {
                return(JsonBadRequest(errorMessage));
            }

            // 現状のノートブック履歴IDに紐づいている親学習をすべて外す。
            notebookHistoryRepository.DetachParentToNotebookAsync(notebookHistory);

            // 親学習が指定されていれば存在チェック
            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;
            }

            // 現状のノートブック履歴IDに紐づいている親推論をすべて外す。
            notebookHistoryRepository.DetachParentInferenceToNotebookAsync(notebookHistory);

            // 親推論が指定されていれば存在チェック
            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;
            }

            // コンテナの実行前に、ノートブック履歴を更新する(コンテナの実行に失敗した場合、そのステータスをユーザに表示するため)
            notebookHistory.DataSetId    = model.DataSetId;
            notebookHistory.Cpu          = model.Cpu.Value;
            notebookHistory.Memory       = model.Memory.Value;
            notebookHistory.Gpu          = model.Gpu.Value;
            notebookHistory.Status       = ContainerStatus.Running.Key;
            notebookHistory.StartedAt    = DateTime.Now;
            notebookHistory.CompletedAt  = null;
            notebookHistory.ExpiresIn    = model.ExpiresIn;
            notebookHistory.LocalDataSet = model.LocalDataSet;
            notebookHistory.EntryPoint   = model.EntryPoint;

            notebookHistoryRepository.Update(notebookHistory);
            unitOfWork.Commit();

            var result = await clusterManagementLogic.RunNotebookContainerAsync(notebookHistory);

            if (result.IsSuccess == false)
            {
                // コンテナの起動に失敗した状態。エラーを出力して、保存したノートブック履歴も削除する。
                notebookHistory.Status      = ContainerStatus.Killed.Key;
                notebookHistory.CompletedAt = DateTime.Now;
                notebookHistoryRepository.Update(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."));
            }
        }