fractal-server 2.17.1__tar.gz → 2.17.1a0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/PKG-INFO +1 -1
- fractal_server-2.17.1a0/fractal_server/__init__.py +1 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/models/__init__.py +1 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/models/security.py +14 -1
- fractal_server-2.17.1a0/fractal_server/app/models/user_settings.py +37 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/models/v2/project.py +4 -1
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/models/v2/task_group.py +4 -1
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/shutdown.py +19 -23
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/config/_main.py +1 -1
- fractal_server-2.17.1a0/fractal_server/data_migrations/2_17_0.py +339 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/pyproject.toml +3 -3
- fractal_server-2.17.1/fractal_server/__init__.py +0 -1
- fractal_server-2.17.1/fractal_server/migrations/versions/45fbb391d7af_make_resource_id_fk_non_nullable.py +0 -46
- fractal_server-2.17.1/fractal_server/migrations/versions/49d0856e9569_drop_table.py +0 -63
- fractal_server-2.17.1/fractal_server/migrations/versions/7673fe18c05d_remove_project_dir_server_default.py +0 -29
- fractal_server-2.17.1/fractal_server/migrations/versions/caba9fb1ea5e_drop_useroauth_user_settings_id.py +0 -49
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/LICENSE +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/README.md +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/__main__.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/alembic.ini +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/__init__.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/db/__init__.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/models/linkusergroup.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/models/linkuserproject.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/models/v2/__init__.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/models/v2/accounting.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/models/v2/dataset.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/models/v2/history.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/models/v2/job.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/models/v2/profile.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/models/v2/resource.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/models/v2/task.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/models/v2/workflow.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/models/v2/workflowtask.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/__init__.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/admin/__init__.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/admin/v2/__init__.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/admin/v2/_aux_functions.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/admin/v2/accounting.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/admin/v2/impersonate.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/admin/v2/job.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/admin/v2/profile.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/admin/v2/project.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/admin/v2/resource.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/admin/v2/task.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/admin/v2/task_group.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/admin/v2/task_group_lifecycle.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/__init__.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/__init__.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/_aux_functions.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/_aux_functions_history.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/_aux_functions_task_lifecycle.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/_aux_functions_task_version_update.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/_aux_functions_tasks.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/_aux_task_group_disambiguation.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/dataset.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/history.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/images.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/job.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/pre_submission_checks.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/project.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/status_legacy.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/submit.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/task.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/task_collection.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/task_collection_custom.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/task_collection_pixi.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/task_group.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/task_group_lifecycle.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/task_version_update.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/workflow.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/workflow_import.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/api/v2/workflowtask.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/auth/__init__.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/auth/_aux_auth.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/auth/current_user.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/auth/group.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/auth/login.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/auth/oauth.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/auth/register.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/auth/router.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/auth/users.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/aux/__init__.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/aux/_job.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/aux/_runner.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/aux/validate_user_profile.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/routes/pagination.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/schemas/__init__.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/schemas/user.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/schemas/user_group.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/schemas/v2/__init__.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/schemas/v2/accounting.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/schemas/v2/dataset.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/schemas/v2/dumps.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/schemas/v2/history.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/schemas/v2/job.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/schemas/v2/manifest.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/schemas/v2/profile.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/schemas/v2/project.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/schemas/v2/resource.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/schemas/v2/status_legacy.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/schemas/v2/task.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/schemas/v2/task_collection.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/schemas/v2/task_group.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/schemas/v2/workflow.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/schemas/v2/workflowtask.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/security/__init__.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/security/signup_email.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/config/__init__.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/config/_data.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/config/_database.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/config/_email.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/config/_oauth.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/config/_settings_config.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/data_migrations/README.md +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/data_migrations/tools.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/exceptions.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/gunicorn_fractal.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/images/__init__.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/images/models.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/images/status_tools.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/images/tools.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/logger.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/main.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/env.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/naming_convention.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/034a469ec2eb_task_groups.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/091b01f51f88_add_usergroup_and_linkusergroup_table.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/0f5f85bb2ae7_add_pre_pinned_packages.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/19eca0dd47a9_user_settings_project_dir.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/1a83a5260664_rename.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/1eac13a26c83_drop_v1_tables.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/316140ff7ee1_remove_usersettings_cache_dir.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/47351f8c7ebc_drop_dataset_filters.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/4c308bcaea2b_add_task_args_schema_and_task_args_.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/4cedeb448a53_workflowtask_foreign_keys_not_nullables.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/501961cfcd85_remove_link_between_v1_and_v2_tasks_.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/50a13d6138fd_initial_schema.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/5bf02391cfef_v2.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/70e77f1c38b0_add_applyworkflow_first_task_index_and_.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/71eefd1dd202_add_slurm_accounts.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/791ce783d3d8_add_indices.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/83bc2ad3ffcc_2_17_0.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/84bf0fffde30_add_dumps_to_applyworkflow.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/8e8f227a3e36_update_taskv2_post_2_7_0.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/8f79bd162e35_add_docs_info_and_docs_link_to_task_.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/94a47ea2d3ff_remove_cache_dir_slurm_user_and_slurm_.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/969d84257cac_add_historyrun_task_id.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/97f444d47249_add_applyworkflow_project_dump.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/981d588fe248_add_executor_error_log.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/99ea79d9e5d2_add_dataset_history.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/9c5ae74c9b98_add_user_settings_table.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/9db60297b8b2_set_ondelete.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/9fd26a2b0de4_add_workflow_timestamp_created.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/a7f4d6137b53_add_workflow_dump_to_applyworkflow.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/af1ef1c83c9b_add_accounting_tables.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/af8673379a5c_drop_old_filter_columns.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/b1e7f7a1ff71_task_group_for_pixi.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/b3ffb095f973_json_to_jsonb.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/c90a7c76e996_job_id_in_history_run.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/d256a7379ab8_taskgroup_activity_and_venv_info_to_.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/d4fe3708d309_make_applyworkflow_workflow_dump_non_.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/da2cb2ac4255_user_group_viewer_paths.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/db09233ad13a_split_filters_and_keep_old_columns.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/e75cac726012_make_applyworkflow_start_timestamp_not_.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/e81103413827_add_job_type_filters.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/efa89c30e0a4_add_project_timestamp_created.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/f37aceb45062_make_historyunit_logfile_required.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/f384e1c0cf5d_drop_task_default_args_columns.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/migrations/versions/fbce16ff4e47_new_history_items.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/py.typed +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/__init__.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/components.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/config/__init__.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/config/_local.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/config/_slurm.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/config/slurm_mem_to_MB.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/exceptions.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/executors/__init__.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/executors/base_runner.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/executors/call_command_wrapper.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/executors/local/__init__.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/executors/local/get_local_config.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/executors/local/runner.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/executors/slurm_common/__init__.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/executors/slurm_common/_batching.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/executors/slurm_common/_job_states.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/executors/slurm_common/base_slurm_runner.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/executors/slurm_common/get_slurm_config.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/executors/slurm_common/remote.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/executors/slurm_common/slurm_config.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/executors/slurm_common/slurm_job_task_models.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/executors/slurm_ssh/__init__.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/executors/slurm_ssh/run_subprocess.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/executors/slurm_ssh/runner.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/executors/slurm_ssh/tar_commands.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/executors/slurm_sudo/__init__.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/executors/slurm_sudo/_subprocess_run_as_user.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/executors/slurm_sudo/runner.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/filenames.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/set_start_and_last_task_index.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/task_files.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/v2/__init__.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/v2/_local.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/v2/_slurm_ssh.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/v2/_slurm_sudo.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/v2/db_tools.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/v2/deduplicate_list.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/v2/merge_outputs.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/v2/runner.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/v2/runner_functions.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/v2/submit_workflow.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/v2/task_interface.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/runner/versions.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/ssh/__init__.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/ssh/_fabric.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/string_tools.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/syringe.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/tasks/__init__.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/tasks/config/__init__.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/tasks/config/_pixi.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/tasks/config/_python.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/tasks/utils.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/__init__.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/local/__init__.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/local/_utils.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/local/collect.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/local/collect_pixi.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/local/deactivate.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/local/deactivate_pixi.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/local/delete.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/local/reactivate.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/local/reactivate_pixi.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/ssh/__init__.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/ssh/_pixi_slurm_ssh.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/ssh/_utils.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/ssh/collect.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/ssh/collect_pixi.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/ssh/deactivate.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/ssh/deactivate_pixi.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/ssh/delete.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/ssh/reactivate.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/ssh/reactivate_pixi.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/templates/1_create_venv.sh +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/templates/2_pip_install.sh +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/templates/3_pip_freeze.sh +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/templates/4_pip_show.sh +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/templates/5_get_venv_size_and_file_number.sh +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/templates/6_pip_install_from_freeze.sh +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/templates/pixi_1_extract.sh +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/templates/pixi_2_install.sh +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/templates/pixi_3_post_install.sh +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/utils_background.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/utils_database.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/utils_package_names.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/utils_pixi.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/utils_python_interpreter.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/tasks/v2/utils_templates.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/types/__init__.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/types/validators/__init__.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/types/validators/_common_validators.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/types/validators/_filter_validators.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/types/validators/_workflow_task_arguments_validators.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/urls.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/utils.py +0 -0
- {fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/zip_tools.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__VERSION__ = "2.17.1a0"
|
|
@@ -95,11 +95,24 @@ class UserOAuth(SQLModel, table=True):
|
|
|
95
95
|
ondelete="RESTRICT",
|
|
96
96
|
)
|
|
97
97
|
|
|
98
|
-
project_dir: str
|
|
98
|
+
# TODO-2.17.1: update to `project_dir: str`
|
|
99
|
+
project_dir: str = Field(
|
|
100
|
+
sa_column=Column(
|
|
101
|
+
String,
|
|
102
|
+
server_default="/PLACEHOLDER",
|
|
103
|
+
nullable=False,
|
|
104
|
+
)
|
|
105
|
+
)
|
|
99
106
|
slurm_accounts: list[str] = Field(
|
|
100
107
|
sa_column=Column(ARRAY(String), server_default="{}"),
|
|
101
108
|
)
|
|
102
109
|
|
|
110
|
+
# TODO-2.17.1: remove
|
|
111
|
+
user_settings_id: int | None = Field(
|
|
112
|
+
foreign_key="user_settings.id",
|
|
113
|
+
default=None,
|
|
114
|
+
)
|
|
115
|
+
|
|
103
116
|
|
|
104
117
|
class UserGroup(SQLModel, table=True):
|
|
105
118
|
"""
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
from sqlalchemy import Column
|
|
2
|
+
from sqlalchemy.dialects.postgresql import JSONB
|
|
3
|
+
from sqlmodel import Field
|
|
4
|
+
from sqlmodel import SQLModel
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
# TODO-2.17.1: Drop `UserSettings`
|
|
8
|
+
class UserSettings(SQLModel, table=True):
|
|
9
|
+
"""
|
|
10
|
+
Comprehensive list of user settings.
|
|
11
|
+
|
|
12
|
+
Attributes:
|
|
13
|
+
id: ID of database object
|
|
14
|
+
slurm_accounts:
|
|
15
|
+
List of SLURM accounts, to be used upon Fractal job submission.
|
|
16
|
+
ssh_host: SSH-reachable host where a SLURM client is available.
|
|
17
|
+
ssh_username: User on `ssh_host`.
|
|
18
|
+
ssh_private_key_path: Path of private SSH key for `ssh_username`.
|
|
19
|
+
slurm_user: Local user, to be impersonated via `sudo -u`
|
|
20
|
+
project_dir: Folder where `slurm_user` can write.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
__tablename__ = "user_settings"
|
|
24
|
+
|
|
25
|
+
id: int | None = Field(default=None, primary_key=True)
|
|
26
|
+
slurm_accounts: list[str] = Field(
|
|
27
|
+
sa_column=Column(JSONB, server_default="[]", nullable=False)
|
|
28
|
+
)
|
|
29
|
+
ssh_host: str | None = None
|
|
30
|
+
ssh_username: str | None = None
|
|
31
|
+
ssh_private_key_path: str | None = None
|
|
32
|
+
|
|
33
|
+
slurm_user: str | None = None
|
|
34
|
+
project_dir: str | None = None
|
|
35
|
+
|
|
36
|
+
ssh_tasks_dir: str | None = None
|
|
37
|
+
ssh_jobs_dir: str | None = None
|
|
@@ -15,7 +15,10 @@ class ProjectV2(SQLModel, table=True):
|
|
|
15
15
|
id: int | None = Field(default=None, primary_key=True)
|
|
16
16
|
name: str
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
# TODO-2.17.1: make `resource_id` not nullable
|
|
19
|
+
resource_id: int | None = Field(
|
|
20
|
+
foreign_key="resource.id", default=None, ondelete="RESTRICT"
|
|
21
|
+
)
|
|
19
22
|
timestamp_created: datetime = Field(
|
|
20
23
|
default_factory=get_timestamp,
|
|
21
24
|
sa_column=Column(DateTime(timezone=True), nullable=False),
|
{fractal_server-2.17.1 → fractal_server-2.17.1a0}/fractal_server/app/models/v2/task_group.py
RENAMED
|
@@ -42,7 +42,10 @@ class TaskGroupV2(SQLModel, table=True):
|
|
|
42
42
|
user_group_id: int | None = Field(
|
|
43
43
|
foreign_key="usergroup.id", default=None, ondelete="SET NULL"
|
|
44
44
|
)
|
|
45
|
-
|
|
45
|
+
# TODO-2.17.1: make `resource_id` not nullable
|
|
46
|
+
resource_id: int | None = Field(
|
|
47
|
+
foreign_key="resource.id", default=None, ondelete="RESTRICT"
|
|
48
|
+
)
|
|
46
49
|
|
|
47
50
|
origin: str
|
|
48
51
|
pkg_name: str
|
|
@@ -12,48 +12,44 @@ from fractal_server.syringe import Inject
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
async def cleanup_after_shutdown(*, jobsV2: list[int], logger_name: str):
|
|
15
|
-
settings = Inject(get_settings)
|
|
16
15
|
logger = get_logger(logger_name)
|
|
17
16
|
logger.info("Cleanup function after shutdown")
|
|
18
|
-
|
|
17
|
+
stm_v2 = (
|
|
19
18
|
select(JobV2)
|
|
20
19
|
.where(JobV2.id.in_(jobsV2))
|
|
21
20
|
.where(JobV2.status == JobStatusTypeV2.SUBMITTED)
|
|
22
21
|
)
|
|
23
|
-
stm_ids = (
|
|
24
|
-
select(JobV2.id)
|
|
25
|
-
.where(JobV2.id.in_(jobsV2))
|
|
26
|
-
.where(JobV2.status == JobStatusTypeV2.SUBMITTED)
|
|
27
|
-
)
|
|
28
22
|
|
|
29
23
|
async for session in get_async_db():
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
for job in
|
|
24
|
+
jobsV2_db = (await session.execute(stm_v2)).scalars().all()
|
|
25
|
+
|
|
26
|
+
for job in jobsV2_db:
|
|
33
27
|
_write_shutdown_file(job=job)
|
|
34
28
|
|
|
35
|
-
|
|
36
|
-
|
|
29
|
+
settings = Inject(get_settings)
|
|
30
|
+
|
|
37
31
|
t_start = time.perf_counter()
|
|
38
32
|
while (
|
|
39
33
|
time.perf_counter() - t_start
|
|
40
|
-
)
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
34
|
+
) < settings.FRACTAL_GRACEFUL_SHUTDOWN_TIME: # 30 seconds
|
|
35
|
+
logger.info("Waiting 3 seconds before checking")
|
|
36
|
+
time.sleep(3)
|
|
37
|
+
jobsV2_db = (await session.execute(stm_v2)).scalars().all()
|
|
38
|
+
|
|
39
|
+
if len(jobsV2_db) == 0:
|
|
40
|
+
logger.info(
|
|
41
|
+
"All jobs associated to this app are "
|
|
42
|
+
"either done or failed. Exit."
|
|
43
|
+
)
|
|
44
44
|
return
|
|
45
45
|
else:
|
|
46
|
-
logger.info(f"Some jobs are still 'submitted'
|
|
47
|
-
logger.info(f"Wait {interval:.4f} seconds before next check.")
|
|
48
|
-
time.sleep(interval)
|
|
46
|
+
logger.info(f"Some jobs are still 'submitted' {jobsV2_db=}")
|
|
49
47
|
logger.info(
|
|
50
48
|
"Graceful shutdown reached its maximum time, "
|
|
51
|
-
"but some jobs are still submitted
|
|
49
|
+
"but some jobs are still submitted"
|
|
52
50
|
)
|
|
53
51
|
|
|
54
|
-
|
|
55
|
-
jobs = (await session.execute(stm_objects)).scalars().all()
|
|
56
|
-
for job in jobs:
|
|
52
|
+
for job in jobsV2_db:
|
|
57
53
|
job.status = "failed"
|
|
58
54
|
job.log = (job.log or "") + "\nJob stopped due to app shutdown\n"
|
|
59
55
|
session.add(job)
|
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import logging
|
|
3
|
+
import sys
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from dotenv.main import DotEnv
|
|
8
|
+
from pydantic import BaseModel
|
|
9
|
+
from sqlalchemy.orm import Session
|
|
10
|
+
from sqlalchemy.sql.operators import is_
|
|
11
|
+
from sqlalchemy.sql.operators import is_not
|
|
12
|
+
from sqlmodel import select
|
|
13
|
+
|
|
14
|
+
from fractal_server.app.db import get_sync_db
|
|
15
|
+
from fractal_server.app.models import Profile
|
|
16
|
+
from fractal_server.app.models import ProjectV2
|
|
17
|
+
from fractal_server.app.models import Resource
|
|
18
|
+
from fractal_server.app.models import TaskGroupV2
|
|
19
|
+
from fractal_server.app.models import UserOAuth
|
|
20
|
+
from fractal_server.app.models import UserSettings
|
|
21
|
+
from fractal_server.app.schemas.v2.profile import cast_serialize_profile
|
|
22
|
+
from fractal_server.app.schemas.v2.resource import cast_serialize_resource
|
|
23
|
+
from fractal_server.config import get_settings
|
|
24
|
+
from fractal_server.runner.config import JobRunnerConfigLocal
|
|
25
|
+
from fractal_server.runner.config import JobRunnerConfigSLURM
|
|
26
|
+
from fractal_server.tasks.config import TasksPixiSettings
|
|
27
|
+
from fractal_server.tasks.config import TasksPythonSettings
|
|
28
|
+
from fractal_server.types import AbsolutePathStr
|
|
29
|
+
from fractal_server.types import ListUniqueNonEmptyString
|
|
30
|
+
from fractal_server.urls import normalize_url
|
|
31
|
+
|
|
32
|
+
logging.basicConfig(level=logging.INFO)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class UserUpdateInfo(BaseModel):
|
|
36
|
+
user_id: int
|
|
37
|
+
project_dir: AbsolutePathStr
|
|
38
|
+
slurm_accounts: ListUniqueNonEmptyString
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class ProfileUsersUpdateInfo(BaseModel):
|
|
42
|
+
data: dict[str, Any]
|
|
43
|
+
user_updates: list[UserUpdateInfo]
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _get_user_settings(user: UserOAuth, db: Session) -> UserSettings:
|
|
47
|
+
if user.user_settings_id is None:
|
|
48
|
+
sys.exit(f"User {user.email} is active but {user.user_settings_id=}.")
|
|
49
|
+
user_settings = db.get(UserSettings, user.user_settings_id)
|
|
50
|
+
return user_settings
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def assert_user_setting_key(
|
|
54
|
+
user: UserOAuth,
|
|
55
|
+
user_settings: UserSettings,
|
|
56
|
+
keys: list[str],
|
|
57
|
+
) -> None:
|
|
58
|
+
for key in keys:
|
|
59
|
+
if getattr(user_settings, key) is None:
|
|
60
|
+
sys.exit(
|
|
61
|
+
f"User {user.email} is active and verified but their "
|
|
62
|
+
f"user settings have {key}=None."
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def prepare_profile_and_user_updates() -> dict[str, ProfileUsersUpdateInfo]:
|
|
67
|
+
settings = get_settings()
|
|
68
|
+
profiles_and_users: dict[str, ProfileUsersUpdateInfo] = {}
|
|
69
|
+
with next(get_sync_db()) as db:
|
|
70
|
+
# Get active&verified users
|
|
71
|
+
res = db.execute(
|
|
72
|
+
select(UserOAuth)
|
|
73
|
+
.where(is_(UserOAuth.is_active, True))
|
|
74
|
+
.where(is_(UserOAuth.is_verified, True))
|
|
75
|
+
.order_by(UserOAuth.id)
|
|
76
|
+
)
|
|
77
|
+
for user in res.unique().scalars().all():
|
|
78
|
+
# Get user settings
|
|
79
|
+
user_settings = _get_user_settings(user=user, db=db)
|
|
80
|
+
assert_user_setting_key(user, user_settings, ["project_dir"])
|
|
81
|
+
|
|
82
|
+
# Prepare profile data and user update
|
|
83
|
+
new_profile_data = dict()
|
|
84
|
+
if settings.FRACTAL_RUNNER_BACKEND == "local":
|
|
85
|
+
username = None
|
|
86
|
+
if settings.FRACTAL_RUNNER_BACKEND == "slurm_sudo":
|
|
87
|
+
assert_user_setting_key(user, user_settings, ["slurm_user"])
|
|
88
|
+
username = user_settings.slurm_user
|
|
89
|
+
elif settings.FRACTAL_RUNNER_BACKEND == "slurm_ssh":
|
|
90
|
+
assert_user_setting_key(
|
|
91
|
+
user,
|
|
92
|
+
user_settings,
|
|
93
|
+
[
|
|
94
|
+
"ssh_username",
|
|
95
|
+
"ssh_private_key_path",
|
|
96
|
+
"ssh_tasks_dir",
|
|
97
|
+
"ssh_jobs_dir",
|
|
98
|
+
],
|
|
99
|
+
)
|
|
100
|
+
username = user_settings.ssh_username
|
|
101
|
+
new_profile_data.update(
|
|
102
|
+
ssh_key_path=user_settings.ssh_private_key_path,
|
|
103
|
+
tasks_remote_dir=normalize_url(
|
|
104
|
+
user_settings.ssh_tasks_dir
|
|
105
|
+
),
|
|
106
|
+
jobs_remote_dir=normalize_url(user_settings.ssh_jobs_dir),
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
new_profile_data.update(
|
|
110
|
+
name=f"Profile {username}",
|
|
111
|
+
username=username,
|
|
112
|
+
resource_type=settings.FRACTAL_RUNNER_BACKEND,
|
|
113
|
+
)
|
|
114
|
+
cast_serialize_profile(new_profile_data)
|
|
115
|
+
|
|
116
|
+
user_update_info = UserUpdateInfo(
|
|
117
|
+
user_id=user.id,
|
|
118
|
+
project_dir=normalize_url(user_settings.project_dir),
|
|
119
|
+
slurm_accounts=user_settings.slurm_accounts or [],
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
if username in profiles_and_users.keys():
|
|
123
|
+
if profiles_and_users[username].data != new_profile_data:
|
|
124
|
+
error_msg = (
|
|
125
|
+
"Profile data mismatch.\n"
|
|
126
|
+
f"{profiles_and_users[username].data=}\n"
|
|
127
|
+
f"{new_profile_data=}"
|
|
128
|
+
)
|
|
129
|
+
logging.error(error_msg)
|
|
130
|
+
sys.exit(error_msg)
|
|
131
|
+
profiles_and_users[username].user_updates.append(
|
|
132
|
+
user_update_info
|
|
133
|
+
)
|
|
134
|
+
else:
|
|
135
|
+
profiles_and_users[username] = ProfileUsersUpdateInfo(
|
|
136
|
+
data=new_profile_data,
|
|
137
|
+
user_updates=[user_update_info],
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
return profiles_and_users
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def get_old_dotenv_variables() -> dict[str, str | None]:
|
|
144
|
+
"""
|
|
145
|
+
See
|
|
146
|
+
https://github.com/fractal-analytics-platform/fractal-server/blob/2.16.x/fractal_server/config.py
|
|
147
|
+
"""
|
|
148
|
+
OLD_DOTENV_FILE = ".fractal_server.env.old"
|
|
149
|
+
return dict(
|
|
150
|
+
**DotEnv(
|
|
151
|
+
dotenv_path=OLD_DOTENV_FILE,
|
|
152
|
+
override=False,
|
|
153
|
+
).dict()
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def get_TasksPythonSettings(
|
|
158
|
+
old_config: dict[str, str | None]
|
|
159
|
+
) -> dict[str, Any]:
|
|
160
|
+
versions = {}
|
|
161
|
+
for version_underscore in ["3_9", "3_10", "3_11", "3_12"]:
|
|
162
|
+
key = f"FRACTAL_TASKS_PYTHON_{version_underscore}"
|
|
163
|
+
version_dot = version_underscore.replace("_", ".")
|
|
164
|
+
value = old_config.get(key, None)
|
|
165
|
+
if value is not None:
|
|
166
|
+
versions[version_dot] = value
|
|
167
|
+
obj = TasksPythonSettings(
|
|
168
|
+
default_version=old_config["FRACTAL_TASKS_PYTHON_DEFAULT_VERSION"],
|
|
169
|
+
versions=versions,
|
|
170
|
+
pip_cache_dir=old_config.get("FRACTAL_PIP_CACHE_DIR", None),
|
|
171
|
+
)
|
|
172
|
+
return obj.model_dump()
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def get_TasksPixiSettings(old_config: dict[str, str | None]) -> dict[str, Any]:
|
|
176
|
+
pixi_file = old_config.get("FRACTAL_PIXI_CONFIG_FILE", None)
|
|
177
|
+
if pixi_file is None:
|
|
178
|
+
return {}
|
|
179
|
+
with open(pixi_file) as f:
|
|
180
|
+
old_pixi_config = json.load(f)
|
|
181
|
+
TasksPixiSettings(**old_pixi_config)
|
|
182
|
+
return old_pixi_config
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def get_JobRunnerConfigSLURM(
|
|
186
|
+
old_config: dict[str, str | None]
|
|
187
|
+
) -> dict[str, Any]:
|
|
188
|
+
slurm_file = old_config["FRACTAL_SLURM_CONFIG_FILE"]
|
|
189
|
+
with open(slurm_file) as f:
|
|
190
|
+
old_slurm_config = json.load(f)
|
|
191
|
+
JobRunnerConfigSLURM(**old_slurm_config)
|
|
192
|
+
return old_slurm_config
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def get_JobRunnerConfigLocal(
|
|
196
|
+
old_config: dict[str, str | None]
|
|
197
|
+
) -> dict[str, Any]:
|
|
198
|
+
local_file = old_config.get("FRACTAL_LOCAL_CONFIG_FILE", None)
|
|
199
|
+
if local_file is None or not Path(local_file).exists():
|
|
200
|
+
return JobRunnerConfigLocal().model_dump()
|
|
201
|
+
else:
|
|
202
|
+
with open(local_file) as f:
|
|
203
|
+
old_local_config = json.load(f)
|
|
204
|
+
JobRunnerConfigLocal(**old_local_config)
|
|
205
|
+
return old_local_config
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def get_ssh_host() -> str:
|
|
209
|
+
with next(get_sync_db()) as db:
|
|
210
|
+
res = db.execute(
|
|
211
|
+
select(UserSettings.ssh_host).where(
|
|
212
|
+
is_not(UserSettings.ssh_host, None)
|
|
213
|
+
)
|
|
214
|
+
)
|
|
215
|
+
hosts = res.scalars().all()
|
|
216
|
+
if len(set(hosts)) > 1:
|
|
217
|
+
host = max(set(hosts), key=hosts.count)
|
|
218
|
+
print(f"MOST FREQUENT HOST: {host}")
|
|
219
|
+
else:
|
|
220
|
+
host = hosts[0]
|
|
221
|
+
return host
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
def prepare_resource_data(old_config: dict[str, str | None]) -> dict[str, Any]:
|
|
225
|
+
settings = get_settings()
|
|
226
|
+
|
|
227
|
+
resource_data = dict(
|
|
228
|
+
type=settings.FRACTAL_RUNNER_BACKEND,
|
|
229
|
+
name="Resource Name",
|
|
230
|
+
tasks_python_config=get_TasksPythonSettings(old_config),
|
|
231
|
+
tasks_pixi_config=get_TasksPixiSettings(old_config),
|
|
232
|
+
tasks_local_dir=old_config["FRACTAL_TASKS_DIR"],
|
|
233
|
+
jobs_local_dir=old_config["FRACTAL_RUNNER_WORKING_BASE_DIR"],
|
|
234
|
+
jobs_poll_interval=int(
|
|
235
|
+
old_config.get("FRACTAL_SLURM_POLL_INTERVAL", 15)
|
|
236
|
+
),
|
|
237
|
+
)
|
|
238
|
+
if settings.FRACTAL_RUNNER_BACKEND == "local":
|
|
239
|
+
resource_data["jobs_runner_config"] = get_JobRunnerConfigLocal(
|
|
240
|
+
old_config
|
|
241
|
+
)
|
|
242
|
+
elif settings.FRACTAL_RUNNER_BACKEND == "slurm_sudo":
|
|
243
|
+
resource_data["jobs_slurm_python_worker"] = old_config[
|
|
244
|
+
"FRACTAL_SLURM_WORKER_PYTHON"
|
|
245
|
+
]
|
|
246
|
+
resource_data["jobs_runner_config"] = get_JobRunnerConfigSLURM(
|
|
247
|
+
old_config
|
|
248
|
+
)
|
|
249
|
+
else:
|
|
250
|
+
resource_data["jobs_slurm_python_worker"] = old_config[
|
|
251
|
+
"FRACTAL_SLURM_WORKER_PYTHON"
|
|
252
|
+
]
|
|
253
|
+
resource_data["jobs_runner_config"] = get_JobRunnerConfigSLURM(
|
|
254
|
+
old_config
|
|
255
|
+
)
|
|
256
|
+
resource_data["host"] = get_ssh_host()
|
|
257
|
+
|
|
258
|
+
resource_data = cast_serialize_resource(resource_data)
|
|
259
|
+
|
|
260
|
+
return resource_data
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
def fix_db():
|
|
264
|
+
logging.info("START preliminary checks.")
|
|
265
|
+
|
|
266
|
+
# Read old env file
|
|
267
|
+
old_config = get_old_dotenv_variables()
|
|
268
|
+
|
|
269
|
+
# Prepare resource data
|
|
270
|
+
logging.info("START prepare_resource_data")
|
|
271
|
+
resource_data = prepare_resource_data(old_config)
|
|
272
|
+
logging.info("END prepare_resource_data")
|
|
273
|
+
|
|
274
|
+
# Prepare profile/users data
|
|
275
|
+
logging.info("START prepare_profile_and_user_updates")
|
|
276
|
+
profile_and_user_updates = prepare_profile_and_user_updates()
|
|
277
|
+
logging.info("END prepare_profile_and_user_updates")
|
|
278
|
+
|
|
279
|
+
logging.info("END preliminary checks.")
|
|
280
|
+
print()
|
|
281
|
+
|
|
282
|
+
with next(get_sync_db()) as db:
|
|
283
|
+
# Create new resource
|
|
284
|
+
resource = Resource(**resource_data)
|
|
285
|
+
db.add(resource)
|
|
286
|
+
db.commit()
|
|
287
|
+
db.refresh(resource)
|
|
288
|
+
db.expunge(resource)
|
|
289
|
+
resource_id = resource.id
|
|
290
|
+
logging.info(f"Created resource with {resource_id=}.")
|
|
291
|
+
|
|
292
|
+
# Update task groups
|
|
293
|
+
res = db.execute(select(TaskGroupV2).order_by(TaskGroupV2.id))
|
|
294
|
+
for taskgroup in res.scalars().all():
|
|
295
|
+
taskgroup.resource_id = resource_id
|
|
296
|
+
db.add(taskgroup)
|
|
297
|
+
db.commit()
|
|
298
|
+
logging.info(f"Set {resource_id=} foreign key for all task groups.")
|
|
299
|
+
|
|
300
|
+
# Update projects
|
|
301
|
+
res = db.execute(select(ProjectV2).order_by(ProjectV2.id))
|
|
302
|
+
for project in res.scalars().all():
|
|
303
|
+
project.resource_id = resource_id
|
|
304
|
+
db.add(project)
|
|
305
|
+
db.commit()
|
|
306
|
+
logging.info(f"Set {resource_id=} foreign key for all projects.")
|
|
307
|
+
print()
|
|
308
|
+
|
|
309
|
+
db.expunge_all()
|
|
310
|
+
|
|
311
|
+
for _, info in profile_and_user_updates.items():
|
|
312
|
+
# Create profile
|
|
313
|
+
profile_data = info.data
|
|
314
|
+
profile_data["resource_id"] = resource_id
|
|
315
|
+
profile = Profile(**profile_data)
|
|
316
|
+
db.add(profile)
|
|
317
|
+
db.commit()
|
|
318
|
+
db.refresh(profile)
|
|
319
|
+
db.expunge(profile)
|
|
320
|
+
profile_id = profile.id
|
|
321
|
+
logging.info(
|
|
322
|
+
f"Created profile '{profile.name}', with {profile.id=}."
|
|
323
|
+
)
|
|
324
|
+
|
|
325
|
+
# Update users
|
|
326
|
+
for user_update in info.user_updates:
|
|
327
|
+
user = db.get(UserOAuth, user_update.user_id)
|
|
328
|
+
user.profile_id = profile_id
|
|
329
|
+
user.project_dir = user_update.project_dir
|
|
330
|
+
user.slurm_accounts = user_update.slurm_accounts
|
|
331
|
+
db.add(user)
|
|
332
|
+
logging.info(f"Updated {user.email} with {user.project_dir=}.")
|
|
333
|
+
logging.info(
|
|
334
|
+
f"Associated {user.email} to profile {profile.name}."
|
|
335
|
+
)
|
|
336
|
+
print()
|
|
337
|
+
db.commit()
|
|
338
|
+
|
|
339
|
+
logging.info("END - all ok.")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "fractal-server"
|
|
3
|
-
version = "2.17.
|
|
3
|
+
version = "2.17.1a0"
|
|
4
4
|
description = "Backend component of the Fractal analytics platform"
|
|
5
5
|
authors = [
|
|
6
6
|
{ name="Tommaso Comparin", email="tommaso.comparin@exact-lab.it" },
|
|
@@ -94,7 +94,7 @@ filterwarnings = [
|
|
|
94
94
|
markers = ["container", "ssh", "fails_on_macos", "oauth"]
|
|
95
95
|
|
|
96
96
|
[tool.bumpver]
|
|
97
|
-
current_version = "2.17.
|
|
97
|
+
current_version = "2.17.1a0"
|
|
98
98
|
version_pattern = "MAJOR.MINOR.PATCH[PYTAGNUM]"
|
|
99
99
|
commit_message = "bump version {old_version} -> {new_version}"
|
|
100
100
|
commit = true
|
|
@@ -130,5 +130,5 @@ POSTGRES_USER="postgres"
|
|
|
130
130
|
POSTGRES_PASSWORD="postgres"
|
|
131
131
|
POSTGRES_DB="fractal_test"
|
|
132
132
|
FRACTAL_API_MAX_JOB_LIST_LENGTH=1
|
|
133
|
-
FRACTAL_GRACEFUL_SHUTDOWN_TIME=
|
|
133
|
+
FRACTAL_GRACEFUL_SHUTDOWN_TIME=1
|
|
134
134
|
FRACTAL_DEFAULT_GROUP_NAME="All"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__VERSION__ = "2.17.1"
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
"""Make resource_id FK non-nullable
|
|
2
|
-
|
|
3
|
-
Revision ID: 45fbb391d7af
|
|
4
|
-
Revises: caba9fb1ea5e
|
|
5
|
-
Create Date: 2025-11-11 16:39:12.813766
|
|
6
|
-
|
|
7
|
-
"""
|
|
8
|
-
import sqlalchemy as sa
|
|
9
|
-
from alembic import op
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
# revision identifiers, used by Alembic.
|
|
13
|
-
revision = "45fbb391d7af"
|
|
14
|
-
down_revision = "caba9fb1ea5e"
|
|
15
|
-
branch_labels = None
|
|
16
|
-
depends_on = None
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
def upgrade() -> None:
|
|
20
|
-
# ### commands auto generated by Alembic - please adjust! ###
|
|
21
|
-
with op.batch_alter_table("projectv2", schema=None) as batch_op:
|
|
22
|
-
batch_op.alter_column(
|
|
23
|
-
"resource_id", existing_type=sa.INTEGER(), nullable=False
|
|
24
|
-
)
|
|
25
|
-
|
|
26
|
-
with op.batch_alter_table("taskgroupv2", schema=None) as batch_op:
|
|
27
|
-
batch_op.alter_column(
|
|
28
|
-
"resource_id", existing_type=sa.INTEGER(), nullable=False
|
|
29
|
-
)
|
|
30
|
-
|
|
31
|
-
# ### end Alembic commands ###
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
def downgrade() -> None:
|
|
35
|
-
# ### commands auto generated by Alembic - please adjust! ###
|
|
36
|
-
with op.batch_alter_table("taskgroupv2", schema=None) as batch_op:
|
|
37
|
-
batch_op.alter_column(
|
|
38
|
-
"resource_id", existing_type=sa.INTEGER(), nullable=True
|
|
39
|
-
)
|
|
40
|
-
|
|
41
|
-
with op.batch_alter_table("projectv2", schema=None) as batch_op:
|
|
42
|
-
batch_op.alter_column(
|
|
43
|
-
"resource_id", existing_type=sa.INTEGER(), nullable=True
|
|
44
|
-
)
|
|
45
|
-
|
|
46
|
-
# ### end Alembic commands ###
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
"""Drop table
|
|
2
|
-
|
|
3
|
-
Revision ID: 49d0856e9569
|
|
4
|
-
Revises: 45fbb391d7af
|
|
5
|
-
Create Date: 2025-11-11 16:39:41.497832
|
|
6
|
-
|
|
7
|
-
"""
|
|
8
|
-
import sqlalchemy as sa
|
|
9
|
-
from alembic import op
|
|
10
|
-
from sqlalchemy.dialects import postgresql
|
|
11
|
-
|
|
12
|
-
# revision identifiers, used by Alembic.
|
|
13
|
-
revision = "49d0856e9569"
|
|
14
|
-
down_revision = "45fbb391d7af"
|
|
15
|
-
branch_labels = None
|
|
16
|
-
depends_on = None
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
def upgrade() -> None:
|
|
20
|
-
# ### commands auto generated by Alembic - please adjust! ###
|
|
21
|
-
op.drop_table("user_settings")
|
|
22
|
-
# ### end Alembic commands ###
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
def downgrade() -> None:
|
|
26
|
-
# ### commands auto generated by Alembic - please adjust! ###
|
|
27
|
-
op.create_table(
|
|
28
|
-
"user_settings",
|
|
29
|
-
sa.Column("id", sa.INTEGER(), autoincrement=True, nullable=False),
|
|
30
|
-
sa.Column(
|
|
31
|
-
"slurm_accounts",
|
|
32
|
-
postgresql.JSONB(astext_type=sa.Text()),
|
|
33
|
-
server_default=sa.text("'[]'::json"),
|
|
34
|
-
autoincrement=False,
|
|
35
|
-
nullable=False,
|
|
36
|
-
),
|
|
37
|
-
sa.Column(
|
|
38
|
-
"ssh_host", sa.VARCHAR(), autoincrement=False, nullable=True
|
|
39
|
-
),
|
|
40
|
-
sa.Column(
|
|
41
|
-
"ssh_username", sa.VARCHAR(), autoincrement=False, nullable=True
|
|
42
|
-
),
|
|
43
|
-
sa.Column(
|
|
44
|
-
"ssh_private_key_path",
|
|
45
|
-
sa.VARCHAR(),
|
|
46
|
-
autoincrement=False,
|
|
47
|
-
nullable=True,
|
|
48
|
-
),
|
|
49
|
-
sa.Column(
|
|
50
|
-
"ssh_tasks_dir", sa.VARCHAR(), autoincrement=False, nullable=True
|
|
51
|
-
),
|
|
52
|
-
sa.Column(
|
|
53
|
-
"ssh_jobs_dir", sa.VARCHAR(), autoincrement=False, nullable=True
|
|
54
|
-
),
|
|
55
|
-
sa.Column(
|
|
56
|
-
"slurm_user", sa.VARCHAR(), autoincrement=False, nullable=True
|
|
57
|
-
),
|
|
58
|
-
sa.Column(
|
|
59
|
-
"project_dir", sa.VARCHAR(), autoincrement=False, nullable=True
|
|
60
|
-
),
|
|
61
|
-
sa.PrimaryKeyConstraint("id", name=op.f("pk_user_settings")),
|
|
62
|
-
)
|
|
63
|
-
# ### end Alembic commands ###
|