public async Task <IActionResult> Create([FromBody] CreateInputModel model, [FromServices] ITenantRepository tenantRepository) { //データの入力チェック if (!ModelState.IsValid) { return(JsonBadRequest("Invalid inputs.")); } //同じ名前のノードは登録できないので、確認する Node node = await nodeRepository.GetByNameAsync(model.Name); if (node != null) { return(JsonConflict($"Node {model.Name} already exists: ID = {node.Id}")); } node = new Node() { Name = model.Name, Memo = model.Memo, Partition = model.Partition, AccessLevel = model.AccessLevel == null ? NodeAccessLevel.Disabled : model.AccessLevel.Value, TensorBoardEnabled = model.TensorBoardEnabled }; if (node.AccessLevel != NodeAccessLevel.Disabled) { //アクセスレベルがDisable以外であれば、k8sとの同期を行う //ノードが存在しない場合を考慮し、もし失敗しても気にせず更新処理を続ける await clusterManagementLogic.UpdatePartitionLabelAsync(node.Name, node.Partition); if (node.TensorBoardEnabled) { await clusterManagementLogic.UpdateTensorBoardEnabledLabelAsync(node.Name, true); } if (node.AccessLevel == NodeAccessLevel.Private) { //テナントをアサイン if (model.AssignedTenantIds != null) { foreach (long tenantId in model.AssignedTenantIds) { if (tenantRepository.Get(tenantId) == null) { return(JsonNotFound($"Tenant ID {tenantId} is not found.")); } } nodeRepository.AssignTenants(node, model.AssignedTenantIds, true); } } } nodeRepository.Add(node); unitOfWork.Commit(); return(JsonCreated(new IndexOutputModel(node))); }
/// <summary> /// DB のテナント・レジストリ・ノード情報を Cluster(k8s)・ObjectStorage へ同期させるメソッドです。 /// </summary> protected override void DoWork(object state, int doWorkCount) { LogInfo($"DB のテナント・レジストリ・ノード情報を Cluster(k8s) へ同期させます。"); try { // DB のテナント情報に対応する名前空間、ロール、クォータを Cluster(k8s) へ同期 var tenants = tenantRepository.GetAllTenants(); foreach (Tenant tenant in tenants) { // 名前空間とロールを同期 bool ret = clusterManagementService.RegistTenantAsync(tenant.Name).Result; if (ret) { LogDebug($"DB のテナント \"{tenant.Name}\" に対応する名前空間とロールを Cluster(k8s) へ同期させました。"); } else { LogError($"DB のテナント \"{tenant.Name}\" に対応する名前空間とロールを Cluster(k8s) へ同期させる処理に失敗しました。"); } // クォータを同期 int cpu = tenant.LimitCpu == null ? 0 : tenant.LimitCpu.Value; int memory = tenant.LimitMemory == null ? 0 : tenant.LimitMemory.Value; int gpu = tenant.LimitGpu == null ? 0 : tenant.LimitGpu.Value; ret = clusterManagementService.SetQuotaAsync(tenant.Name, cpu, memory, gpu).Result; string quotaInfo = $"cpu={cpu} memory={memory} gpu={gpu}"; if (ret) { LogDebug($"DB のテナント \"{tenant.Name}\" に対応するクォータ [{quotaInfo}] を Cluster(k8s) へ同期させました。"); } if (!ret) { LogError($"DB のテナント \"{tenant.Name}\" に対応するクォータ [{quotaInfo}] を Cluster(k8s) へ同期させる処理に失敗しました。"); } // テナントの古い ClusterToken を削除 tenantRepository.DeleteClusterToken(tenant.Id); // ObjectStorage への同期処理を行う if (tenant.Storage != null) { // ObjectStorage に バケットを作成する storageLogic.CreateBucketAsync(tenant, tenant.Storage); } } // テナントの古い ClusterToken 削除を確定する unitOfWork.Commit(); // DB のレジストリ情報(UserTenantRegistryMap)に対応するシークレットを Cluster(k8s) へ同期 var userTenantRegistryMaps = registryRepository.GetUserTenantRegistryMapAll(); foreach (UserTenantRegistryMap userTenantRegistryMap in userTenantRegistryMaps) { // ログ情報 string registryPasswd = string.IsNullOrEmpty(userTenantRegistryMap.RegistryPassword) ? "無し" : "有り"; string mapInfo = $"UserTenantRegistryMapId={userTenantRegistryMap.Id}, UserId={userTenantRegistryMap.UserId}, " + $"RegistryPassword={registryPasswd}, TenantRegistryMapId={userTenantRegistryMap.TenantRegistryMapId}, " + $"TernantId={userTenantRegistryMap.TenantRegistryMap.TenantId}, " + $"RegistryId={userTenantRegistryMap.TenantRegistryMap.RegistryId}"; Registry registry = userTenantRegistryMap.Registry; if (registry == null) { // Registry が null というのはあり得ないが、取り敢えずはチェック LogDebug($"DB のレジストリ情報 [{mapInfo}] に対応する Registry が存在しません。"); continue; } mapInfo += $", RegistryServiceType={registry.ServiceType}"; // テナントの取得 Tenant tenant = tenantRepository.Get(userTenantRegistryMap.TenantRegistryMap.TenantId); if (tenant == null) { // テナントが null というのはあり得ないが、取り敢えずはチェック LogError($"DB のレジストリ情報 [{ mapInfo}] に対応するテナントが存在しません。"); continue; } // RegistryService の取得 IRegistryService registryService = GetRegistryService(registry); if (registryService == null) { LogError($"DB のレジストリ情報 [{mapInfo}] に対応する RegistryService を取得できませんでした。"); continue; } // パスワードが空なら同期させない if (string.IsNullOrEmpty(userTenantRegistryMap.RegistryPassword)) { LogDebug($"DB のレジストリ情報 [{mapInfo}] のレジストリ・パスワードが空なので Cluster(k8s) への同期は行いません。"); continue; } // Docker コンフィグの取得 string dockerCfg = registryService.GetDockerCfgAuthString(userTenantRegistryMap); if (dockerCfg == null) { LogError($"DB のレジストリ情報 [{ mapInfo}] に同期させる Docker コンフィグを取得できませんでした。"); continue; } // シークレット情報の生成 var inModel = new RegistRegistryTokenInputModel() { TenantName = tenant.Name, RegistryTokenKey = userTenantRegistryMap.RegistryTokenKey, DockerCfgAuthString = dockerCfg, Url = userTenantRegistryMap.Registry.RegistryUrl }; // Cluster(k8s) にシークレットを同期 bool ret = clusterManagementService.RegistRegistryTokenyAsync(inModel).Result; if (ret) { LogDebug($"DB のレジストリ情報 [{mapInfo}] に対応するシークレットを Cluster(k8s) へ同期させました。"); } else { LogError($"DB のレジストリ情報 [{mapInfo}] に対応するシークレットを Cluster(k8s) へ同期させる処理に失敗しました。"); } } // DB のノード情報に対応するパーティションを Cluster(k8s) へ同期 var nodes = nodeRepository.GetAll(); foreach (Node node in nodes) { bool ret = clusterManagementLogic.UpdatePartitionLabelAsync(node.Name, node.Partition).Result; if (!ret) { LogError($"DB のノード情報 [{node.Name}] に対応するパーティションを Cluster(k8s) へ同期させる処理に失敗しました。"); continue; } ret = clusterManagementLogic.UpdateTensorBoardEnabledLabelAsync(node.Name, node.TensorBoardEnabled).Result; if (ret) { LogDebug($"DB のノード情報 [{node.Name}] に対応する TensorBoard 可否設定を Cluster(k8s) へ同期させました。"); } else { LogError($"DB のノード情報 [{node.Name}] に対応する TensorBoard 可否設定を Cluster(k8s) へ同期させる処理に失敗しました。"); } ret = clusterManagementLogic.UpdateNotebookEnabledLabelAsync(node.Name, node.NotebookEnabled).Result; if (ret) { LogDebug($"DB のノード情報 [{node.Name}] に対応する Notebook 可否設定を Cluster(k8s) へ同期させました。"); } else { LogError($"DB のノード情報 [{node.Name}] に対応する Notebook 可否設定を Cluster(k8s) へ同期させる処理に失敗しました。"); } // KQI管理者用名前空間の実行可否設定を Cluster(k8s) へ同期する ret = SyncKqiAdminEnabledLabel(node).Result; if (ret) { LogDebug($"DB のノード [{node.Name}] に対応する KQI管理者用名前空間 [{containerManageOptions.KqiAdminNamespace}] のアクセス可否設定を Cluster(k8s) へ同期させました。"); } else { LogError($"DB のノード [{node.Name}] に対応する KQI管理者用名前空間 [{containerManageOptions.KqiAdminNamespace}] のアクセス可否設定を Cluster(k8s) へ同期させる処理に失敗しました。"); } // テナントの実行可否設定を Cluster(k8s) へ同期する int failedCount = SyncTenantEnabledLabel(node).Result; if (failedCount == 0) { LogInfo($"DB のノード [{node.Name}] に対するテナントの実行可否設定情報を Cluster(k8s) へ同期させる処理は終了しました。"); } else { LogError($"DB のノード [{node.Name}] に対するテナントの実行可否設定情報 {failedCount} 件の Cluster(k8s) へ同期させる処理に失敗しました。"); } } LogInfo("DB のテナント・レジストリ・ノード情報を Cluster(k8s) へ同期させる処理は終了しました。"); } catch (Exception e) { //例外をキャッチしたが ERROR ログを出力して処理を継続 LogError($"DB のテナント・レジストリ・ノード情報を Cluster(k8s) へ同期させる時に例外をキャッチしましたが web-api は継続処理します。 例外メッセージ=\"{e.Message}\""); } }