From a3c141e4e1f23c0878992a00dac1b7b11512b893 Mon Sep 17 00:00:00 2001 From: Nate Coraor Date: Thu, 7 Apr 2022 16:14:03 -0400 Subject: [PATCH 01/10] Support Running Galaxy 22.01+ with Gravity. Also support systemd user scope. --- .gitignore | 1 + defaults/main.yml | 21 ++++++++++++++++++-- handlers/main.yml | 30 +++++++++++++++++------------ tasks/dependencies.yml | 9 +++++++++ tasks/gravity.yml | 21 ++++++++++++++++++++ tasks/main.yml | 15 ++++++++++++++- tasks/paths.yml | 29 ---------------------------- tasks/systemd-mule.yml | 9 +++++---- tasks/user-facts.yml | 30 +++++++++++++++++++++++++++++ templates/galaxy.yml.j2 | 3 +++ templates/systemd/galaxy.service.j2 | 5 ++++- 11 files changed, 124 insertions(+), 49 deletions(-) create mode 100644 tasks/gravity.yml create mode 100644 tasks/user-facts.yml diff --git a/.gitignore b/.gitignore index a295864..96eac8b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ *.pyc __pycache__ +*.swp diff --git a/defaults/main.yml b/defaults/main.yml index 6c59639..b9266ad 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -19,6 +19,7 @@ galaxy_fetch_dependencies: yes galaxy_build_client: yes galaxy_manage_errordocs: no galaxy_backup_configfiles: yes +galaxy_manage_gravity: yes galaxy_manage_systemd: no # For Galaxy galaxy_manage_systemd_reports: no # For Reports @@ -242,6 +243,14 @@ galaxy_errordocs_prefix: /error galaxy_config_files: [] galaxy_config_templates: [] +# Default Gravity configuration +galaxy_gravity_state_dir: "{{ (galaxy_mutable_data_dir, 'gravity') | path_join }}" +galaxy_gravity_config_default: + galaxy_root: "{{ galaxy_server_dir }}" + # TODO: log_dir + virtualenv: "{{ galaxy_venv_dir }}" + app_server: gunicorn + # Default uWSGI configuration galaxy_uwsgi_yaml_parser: internal galaxy_uwsgi_config_default: @@ -288,15 +297,23 @@ galaxy_client_build_steps: - plugins # Restart handler is already set if using the systemd options in this role, otherwise you need to define one yourself -galaxy_restart_handler_name: "{{ 'galaxy mule restart' if (galaxy_systemd_mode == 'mule' and galaxy_manage_systemd) else 'default restart galaxy handler' }}" +galaxy_restart_handler_name: "{{ 'galaxy ' ~ galaxy_systemd_mode ~ ' restart' if galaxy_manage_systemd else 'default restart galaxy handler' }}" # # systemd options # -# Currently `mule` is the only systemd mode +# Currently `mule` (aka uWSGI) and `gravity` (runs Galaxy 22.01+ under gunicorn) are supported galaxy_systemd_mode: mule +# Control whether the systemd service unit is installed/controlled as root or the Galaxy user +galaxy_systemd_root: true + +galaxy_systemd_command: "{{ __galaxy_systemd_command[galaxy_systemd_mode] }}" +__galaxy_systemd_command: + mule: "{{ galaxy_venv_dir }}/bin/uwsgi {{ '--yaml' if galaxy_config_style in ('yaml', 'yml') else '--ini' }} {{ galaxy_config_file }}" + gravity: "{{ galaxy_venv_dir }}/bin/galaxyctl start --foreground --quiet" + # Systemd will create cgroups to enforce these limits (sizes in GB), override individual limits by setting # `galaxy_systemd_memory_limit.` in your vars. __galaxy_systemd_memory_limit: diff --git a/handlers/main.yml b/handlers/main.yml index 5f59f60..4dd3a49 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -6,24 +6,30 @@ debug: msg: "RESTARTER NOT IMPLEMENTED - Please restart Galaxy manually. You can define your own handler and enable it with `galaxy_restart_handler_name`" -- name: email administrator with commit id - mail: - from: "{{ galaxy_admin_email_from | default( 'root' ) }}" - to: "{{ galaxy_admin_email_to }}" - subject: "Galaxy instance {{ galaxy_instance_hostname | default( inventory_hostname ) }} is at commit {{ galaxy_commit_id }}" - body: " " - when: galaxy_admin_email_to is defined - - name: daemon reload systemd: daemon_reload: yes + scope: "{{ galaxy_systemd_root | ternary(omit, 'user') }}" - name: galaxy mule start systemd: - name: galaxy.service - state: started + name: galaxy.service + state: started + scope: "{{ galaxy_systemd_root | ternary(omit, 'user') }}" - name: galaxy mule restart systemd: - name: galaxy.service - state: restarted + name: galaxy.service + state: restarted + scope: "{{ galaxy_systemd_root | ternary(omit, 'user') }}" + +- name: galaxy gravity start + systemd: + name: galaxy.service + state: started + scope: "{{ galaxy_systemd_root | ternary(omit, 'user') }}" + +- name: galaxy gravity restart + command: "{{ galaxy_venv_dir }}/bin/galaxyctl graceful" + environment: + GRAVITY_STATE_DIR: "{{ galaxy_gravity_state_dir }}" diff --git a/tasks/dependencies.yml b/tasks/dependencies.yml index b02c016..d7fbd82 100644 --- a/tasks/dependencies.yml +++ b/tasks/dependencies.yml @@ -46,6 +46,15 @@ VIRTUAL_ENV: "{{ galaxy_venv_dir }}" when: galaxy_additional_venv_packages + - name: Configure $GRAVITY_STATE_DIR in virtualenv activate + blockinfile: + path: "{{ galaxy_venv_dir }}/bin/activate" + marker: "# {mark} GALAXYPROJECT.GALAXY ROLE ANSIBLE MANAGED BLOCK" + block: | + # Galaxy Gravity per-instance state directory configured by galaxyproject.galaxy Ansible role + GRAVITY_STATE_DIR={{ galaxy_gravity_state_dir | quote }} + export GRAVITY_STATE_DIR + remote_user: "{{ galaxy_remote_users.privsep | default(__galaxy_remote_user) }}" become: "{{ true if galaxy_become_users.privsep is defined else __galaxy_become }}" become_user: "{{ galaxy_become_users.privsep | default(__galaxy_become_user) }}" diff --git a/tasks/gravity.yml b/tasks/gravity.yml new file mode 100644 index 0000000..2630a86 --- /dev/null +++ b/tasks/gravity.yml @@ -0,0 +1,21 @@ +--- +# Configure Gravity + +- name: Gravity setup + block: + + - name: Register Galaxy config with Gravity + command: "{{ galaxy_venv_dir }}/bin/galaxyctl register {{ galaxy_config_file }}" + args: + creates: "{{ galaxy_gravity_state_dir }}/configstate.yaml" + + - name: Update Gravity process management files + command: "{{ galaxy_venv_dir }}/bin/galaxyctl update" + args: + creates: "{{ galaxy_gravity_state_dir }}/supervisor/supervisord.conf.d" + + environment: + GRAVITY_STATE_DIR: "{{ galaxy_gravity_state_dir }}" + remote_user: "{{ galaxy_remote_users.galaxy | default(__galaxy_remote_user) }}" + become: "{{ true if galaxy_become_users.galaxy is defined else __galaxy_become }}" + become_user: "{{ galaxy_become_users.galaxy | default(__galaxy_become_user) }}" diff --git a/tasks/main.yml b/tasks/main.yml index 14c2598..3a5105f 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -35,6 +35,10 @@ tags: - galaxy_create_user +- name: Collect Galaxy user facts + import_tasks: user-facts.yml + tags: always + - name: Include path management tasks include_tasks: file: paths.yml @@ -121,12 +125,21 @@ tags: - galaxy_manage_errordocs +- name: Include Gravity setup tasks + include_tasks: + file: gravity.yml + apply: + tags: galaxy_manage_gravity + when: galaxy_manage_gravity + tags: + - galaxy_manage_gravity + - name: Include systemd unit setup tasks (Mules) include_tasks: file: systemd-mule.yml apply: tags: galaxy_manage_systemd - when: galaxy_manage_systemd and galaxy_systemd_mode == "mule" + when: galaxy_manage_systemd and galaxy_systemd_mode in ["mule", "gravity"] tags: - galaxy_manage_systemd diff --git a/tasks/paths.yml b/tasks/paths.yml index 1499865..a1e49d7 100644 --- a/tasks/paths.yml +++ b/tasks/paths.yml @@ -3,35 +3,6 @@ - name: Manage Paths block: - - name: Get group IDs for Galaxy users - getent: - database: passwd - key: "{{ item }}" - with_items: - - "{{ __galaxy_user_name }}" - - "{{ __galaxy_privsep_user_name }}" - when: galaxy_group is not defined - register: __galaxy_passwd_result - - - name: Get group names for Galaxy users - getent: - database: group - key: "{{ item.ansible_facts.getent_passwd[item.invocation.module_args.key][2] }}" - with_items: "{{ __galaxy_passwd_result.results }}" - loop_control: - label: "{{ item.item }}" - when: galaxy_group is not defined - register: __galaxy_group_result - - - name: Set Galaxy user facts - set_fact: - __galaxy_user_group: "{{ ((galaxy_group | default({})).name | default(galaxy_group)) if galaxy_group is defined else (__galaxy_group_result.results[0].ansible_facts.getent_group.keys() | first) }}" - __galaxy_privsep_user_group: "{{ ((galaxy_group | default({})).name | default(galaxy_group)) if galaxy_group is defined else (__galaxy_group_result.results[1].ansible_facts.getent_group.keys() | first) }}" - - - name: Determine whether to restrict to group permissions - set_fact: - __galaxy_dir_perms: "{{ '0750' if __galaxy_user_group == __galaxy_privsep_user_group else '0755' }}" - # try to become root. if you need something fancier, don't use the role and write your own - name: Create galaxy_root file: diff --git a/tasks/systemd-mule.yml b/tasks/systemd-mule.yml index 3d7a93a..c9b5250 100644 --- a/tasks/systemd-mule.yml +++ b/tasks/systemd-mule.yml @@ -5,19 +5,20 @@ - name: Deploy Galaxy Unit template: - owner: root - group: root + owner: "{{ galaxy_systemd_root | ternary('root', omit) }}" + group: "{{ galaxy_systemd_root | ternary('root', omit) }}" mode: 0644 src: systemd/galaxy.service.j2 - dest: /etc/systemd/system/galaxy.service + dest: "{{ galaxy_systemd_root | ternary('/etc/systemd/system/', ('~' ~ __galaxy_user_name ~ '/.config/systemd/user') | expanduser) }}/galaxy.service" notify: - daemon reload - - galaxy mule restart + - "{{ galaxy_restart_handler_name }}" - name: Enable Galaxy Unit systemd: name: galaxy.service enabled: yes + scope: "{{ galaxy_systemd_root | ternary(omit, 'user') }}" remote_user: "{{ galaxy_remote_users.root | default(__galaxy_remote_user) }}" become: "{{ true if galaxy_become_users.root is defined else __galaxy_become }}" diff --git a/tasks/user-facts.yml b/tasks/user-facts.yml new file mode 100644 index 0000000..95e9378 --- /dev/null +++ b/tasks/user-facts.yml @@ -0,0 +1,30 @@ +--- + +- name: Get group IDs for Galaxy users + getent: + database: passwd + key: "{{ item }}" + with_items: + - "{{ __galaxy_user_name }}" + - "{{ __galaxy_privsep_user_name }}" + when: galaxy_group is not defined + register: __galaxy_passwd_result + +- name: Get group names for Galaxy users + getent: + database: group + key: "{{ item.ansible_facts.getent_passwd[item.invocation.module_args.key][2] }}" + with_items: "{{ __galaxy_passwd_result.results }}" + loop_control: + label: "{{ item.item }}" + when: galaxy_group is not defined + register: __galaxy_group_result + +- name: Set Galaxy user facts + set_fact: + __galaxy_user_group: "{{ ((galaxy_group | default({})).name | default(galaxy_group)) if galaxy_group is defined else (__galaxy_group_result.results[0].ansible_facts.getent_group.keys() | first) }}" + __galaxy_privsep_user_group: "{{ ((galaxy_group | default({})).name | default(galaxy_group)) if galaxy_group is defined else (__galaxy_group_result.results[1].ansible_facts.getent_group.keys() | first) }}" + +- name: Determine whether to restrict to group permissions + set_fact: + __galaxy_dir_perms: "{{ '0750' if __galaxy_user_group == __galaxy_privsep_user_group else '0755' }}" diff --git a/templates/galaxy.yml.j2 b/templates/galaxy.yml.j2 index d5af8c4..72bbed9 100644 --- a/templates/galaxy.yml.j2 +++ b/templates/galaxy.yml.j2 @@ -9,6 +9,9 @@ {% endif %} +{% set _gravity_config = galaxy_config.gravity | default(galaxy_gravity_config_default) -%} +{{ {'gravity': _gravity_config} | to_nice_yaml(indent=4) }} + {% set _uwsgi_config = galaxy_config.uwsgi | default(galaxy_uwsgi_config_default) -%} {% if galaxy_uwsgi_yaml_parser == 'libyaml' %} {{ {'uwsgi': _uwsgi_config} | to_nice_yaml(indent=4) }} diff --git a/templates/systemd/galaxy.service.j2 b/templates/systemd/galaxy.service.j2 index 692276c..7cca822 100644 --- a/templates/systemd/galaxy.service.j2 +++ b/templates/systemd/galaxy.service.j2 @@ -6,17 +6,20 @@ After=time-sync.target [Service] UMask=022 Type=simple +{% if galaxy_systemd_root %} User={{ __galaxy_user_name }} Group={{ __galaxy_user_group }} +{% endif %} WorkingDirectory={{ galaxy_server_dir }} TimeoutStartSec=10 -ExecStart={{ galaxy_venv_dir }}/bin/uwsgi {{ '--yaml' if galaxy_config_style in ('yaml', 'yml') else '--ini' }} {{ galaxy_config_file }} +ExecStart={{ galaxy_systemd_command }} Environment=HOME={{ galaxy_root }} Environment=VIRTUAL_ENV={{ galaxy_venv_dir }} Environment=PATH={{ galaxy_venv_dir }}/bin:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin Environment=DOCUTILSCONFIG= Environment=PYTHONPATH={{ galaxy_dynamic_job_rules_dir }} +Environment=GRAVITY_STATE_DIR={{ galaxy_gravity_state_dir }} {% for env in galaxy_systemd_env %} Environment={{ env }} {% endfor %} From 858395ec4b5a12f7780e92025d6ac22d322d658c Mon Sep 17 00:00:00 2001 From: Nate Coraor Date: Thu, 7 Apr 2022 16:44:53 -0400 Subject: [PATCH 02/10] Graceful restarts with systemd --- defaults/main.yml | 3 +++ templates/systemd/galaxy.service.j2 | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/defaults/main.yml b/defaults/main.yml index b9266ad..a5bbdad 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -314,6 +314,9 @@ __galaxy_systemd_command: mule: "{{ galaxy_venv_dir }}/bin/uwsgi {{ '--yaml' if galaxy_config_style in ('yaml', 'yml') else '--ini' }} {{ galaxy_config_file }}" gravity: "{{ galaxy_venv_dir }}/bin/galaxyctl start --foreground --quiet" +# TimeoutStartSec is unfortunately also the timeout used for reload operations, which take longer +galaxy_systemd_timeout_start_sec: "{{ (galaxy_systemd_mode == 'gravity') | ternary(60, 10) }}" + # Systemd will create cgroups to enforce these limits (sizes in GB), override individual limits by setting # `galaxy_systemd_memory_limit.` in your vars. __galaxy_systemd_memory_limit: diff --git a/templates/systemd/galaxy.service.j2 b/templates/systemd/galaxy.service.j2 index 7cca822..c9d8181 100644 --- a/templates/systemd/galaxy.service.j2 +++ b/templates/systemd/galaxy.service.j2 @@ -11,8 +11,12 @@ User={{ __galaxy_user_name }} Group={{ __galaxy_user_group }} {% endif %} WorkingDirectory={{ galaxy_server_dir }} -TimeoutStartSec=10 +TimeoutStartSec={{ galaxy_systemd_timeout_start_sec }} ExecStart={{ galaxy_systemd_command }} +{% if galaxy_systemd_mode == 'gravity' %} +ExecReload={{ galaxy_venv_dir }}/bin/galaxyctl graceful +ExecStop={{ galaxy_venv_dir }}/bin/galaxyctl shutdown +{% endif %} Environment=HOME={{ galaxy_root }} Environment=VIRTUAL_ENV={{ galaxy_venv_dir }} From 4904d274cf5858981e0874a5107f573a5f4b15e8 Mon Sep 17 00:00:00 2001 From: Nate Coraor Date: Thu, 7 Apr 2022 18:21:50 -0400 Subject: [PATCH 03/10] Support gravity log_dir with galaxy_log_dir, and run galaxyctl update as needed --- defaults/main.yml | 9 ++++++++- handlers/main.yml | 10 +++++++++- tasks/static_setup.yml | 1 + 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index a5bbdad..300d846 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -91,6 +91,9 @@ __galaxy_privsep_user_name: "{{ galaxy_privsep_user.name | default(galaxy_privse # If `galaxy_create_user` is enabled, the privsep user will also be created, but you can override this behavior galaxy_create_privsep_user: "{{ galaxy_create_user if __galaxy_privsep_user_name != 'root' else false }}" +# Where to write Galaxy logs to +galaxy_log_dir: "{{ galaxy_mutable_data_dir }}/log" + # Directories to create as the Galaxy user if galaxy_manage_paths is enabled galaxy_dirs: - "{{ galaxy_mutable_data_dir }}" @@ -101,6 +104,7 @@ galaxy_dirs: - "{{ galaxy_file_path }}" - "{{ galaxy_job_working_directory }}" - "{{ galaxy_tool_data_path }}" + - "{{ galaxy_log_dir }}" # Directories to create as the privilege separated user if galaxy_manage_paths is enabled galaxy_privsep_dirs: @@ -247,9 +251,11 @@ galaxy_config_templates: [] galaxy_gravity_state_dir: "{{ (galaxy_mutable_data_dir, 'gravity') | path_join }}" galaxy_gravity_config_default: galaxy_root: "{{ galaxy_server_dir }}" - # TODO: log_dir + log_dir: "{{ galaxy_log_dir }}" virtualenv: "{{ galaxy_venv_dir }}" app_server: gunicorn + gunicorn: + bind: localhost:8080 # Default uWSGI configuration galaxy_uwsgi_yaml_parser: internal @@ -298,6 +304,7 @@ galaxy_client_build_steps: # Restart handler is already set if using the systemd options in this role, otherwise you need to define one yourself galaxy_restart_handler_name: "{{ 'galaxy ' ~ galaxy_systemd_mode ~ ' restart' if galaxy_manage_systemd else 'default restart galaxy handler' }}" +galaxy_galaxyctl_update_handler_name: "{{ 'galaxyctl update' if galaxy_systemd_mode == 'gravity' else 'default galaxyctl update handler' }}" # # systemd options diff --git a/handlers/main.yml b/handlers/main.yml index 4dd3a49..01a81bb 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -1,11 +1,14 @@ --- # defaults file for galaxyproject.galaxy -# TODO: Magical restarters depending on how you're running Galaxy. - name: default restart galaxy handler debug: msg: "RESTARTER NOT IMPLEMENTED - Please restart Galaxy manually. You can define your own handler and enable it with `galaxy_restart_handler_name`" +- name: default galaxyctl update handler + debug: + msg: "No-op for non-Gravity-managed Galaxy, this can be ignored" + - name: daemon reload systemd: daemon_reload: yes @@ -33,3 +36,8 @@ command: "{{ galaxy_venv_dir }}/bin/galaxyctl graceful" environment: GRAVITY_STATE_DIR: "{{ galaxy_gravity_state_dir }}" + +- name: galaxyctl update + command: "{{ galaxy_venv_dir }}/bin/galaxyctl update" + environment: + GRAVITY_STATE_DIR: "{{ galaxy_gravity_state_dir }}" diff --git a/tasks/static_setup.yml b/tasks/static_setup.yml index 70b6c86..025e0e1 100644 --- a/tasks/static_setup.yml +++ b/tasks/static_setup.yml @@ -127,6 +127,7 @@ backup: "{{ galaxy_backup_configfiles }}" mode: "{{ galaxy_config_perms }}" notify: + - "{{ galaxy_galaxyctl_update_handler_name }}" - "{{ galaxy_restart_handler_name }}" remote_user: "{{ galaxy_remote_users.privsep | default(__galaxy_remote_user) }}" From 5c218de140f93305655ae17daee3dd05e759bda4 Mon Sep 17 00:00:00 2001 From: Nate Coraor Date: Thu, 7 Apr 2022 18:33:55 -0400 Subject: [PATCH 04/10] Drop notify of dropped email handler --- tasks/clone.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/tasks/clone.yml b/tasks/clone.yml index 165d23d..db5a532 100644 --- a/tasks/clone.yml +++ b/tasks/clone.yml @@ -16,7 +16,6 @@ register: __galaxy_git_update_result notify: - "{{ galaxy_restart_handler_name }}" - - email administrator with commit id - name: Report Galaxy version change debug: From 68c3bc7193550f74b09ce396af9c60501fbaab41 Mon Sep 17 00:00:00 2001 From: Nate Coraor Date: Thu, 7 Apr 2022 18:48:40 -0400 Subject: [PATCH 05/10] Apparently forgot that when clauses work on handlers --- defaults/main.yml | 1 - handlers/main.yml | 5 +---- tasks/static_setup.yml | 2 +- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 300d846..654c85e 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -304,7 +304,6 @@ galaxy_client_build_steps: # Restart handler is already set if using the systemd options in this role, otherwise you need to define one yourself galaxy_restart_handler_name: "{{ 'galaxy ' ~ galaxy_systemd_mode ~ ' restart' if galaxy_manage_systemd else 'default restart galaxy handler' }}" -galaxy_galaxyctl_update_handler_name: "{{ 'galaxyctl update' if galaxy_systemd_mode == 'gravity' else 'default galaxyctl update handler' }}" # # systemd options diff --git a/handlers/main.yml b/handlers/main.yml index 01a81bb..b6cf61b 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -5,10 +5,6 @@ debug: msg: "RESTARTER NOT IMPLEMENTED - Please restart Galaxy manually. You can define your own handler and enable it with `galaxy_restart_handler_name`" -- name: default galaxyctl update handler - debug: - msg: "No-op for non-Gravity-managed Galaxy, this can be ignored" - - name: daemon reload systemd: daemon_reload: yes @@ -41,3 +37,4 @@ command: "{{ galaxy_venv_dir }}/bin/galaxyctl update" environment: GRAVITY_STATE_DIR: "{{ galaxy_gravity_state_dir }}" + when: "galaxy_systemd_mode == 'gravity'" diff --git a/tasks/static_setup.yml b/tasks/static_setup.yml index 025e0e1..e714e44 100644 --- a/tasks/static_setup.yml +++ b/tasks/static_setup.yml @@ -127,7 +127,7 @@ backup: "{{ galaxy_backup_configfiles }}" mode: "{{ galaxy_config_perms }}" notify: - - "{{ galaxy_galaxyctl_update_handler_name }}" + - galaxyctl update - "{{ galaxy_restart_handler_name }}" remote_user: "{{ galaxy_remote_users.privsep | default(__galaxy_remote_user) }}" From 5e4ee51baefa73eefc25b3a282cc623a9ea4411e Mon Sep 17 00:00:00 2001 From: Nate Coraor Date: Fri, 15 Apr 2022 16:38:02 -0400 Subject: [PATCH 06/10] Automagic restart handlers --- README.md | 35 ++++++++++++++++--- defaults/main.yml | 6 ++-- handlers/main.yml | 20 +++++------ tasks/clone.yml | 2 +- tasks/main.yml | 4 +-- tasks/static_setup.yml | 6 ++-- .../{systemd-mule.yml => systemd-galaxy.yml} | 11 ++++-- 7 files changed, 55 insertions(+), 29 deletions(-) rename tasks/{systemd-mule.yml => systemd-galaxy.yml} (76%) diff --git a/README.md b/README.md index 12b4f1d..731dbbe 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,16 @@ Options below that control individual file or subdirectory placement can still o [custom]: vars/layout-custom.yml [fhs]: http://www.pathname.com/fhs/ +**New options for Galaxy 22.01 and later** + +The role can now manage the Galaxy service using [gravity][gravity]. This is the default for Galaxy 22.05 and later. +Additionally, support for the `galaxy_restart_handler_name` variable has been removed. If you need to enable your own +custom restart handler, you can use the "`listen`" option to the handler as explained in the +[handler documentation](https://docs.ansible.com/ansible/latest/user_guide/playbooks_handlers.html#using-variables-with-handlers). +The handler should "listen" to the topic `"restart galaxy"`. + +[gravity]: https://github.com/galaxyproject/gravity + **New options for Galaxy 18.01 and later** - `galaxy_config_style` (default: `yaml`): The type of Galaxy configuration file to write, `yaml` for the YAML format supported by uWSGI or `ini-paste` for the traditional PasteDeploy-style INI file @@ -223,10 +233,13 @@ Several variables control which functions this role will perform (all default to - `galaxy_build_client`: Build the Galaxy client application (web UI). - `galaxy_client_make_target` (default: `client-production-maps`): Set the client build type. Options include: `client`, `client-production` and `client-production-maps`. See [Galaxy client readme][client-build] for details. +- `galaxy_manage_systemd` (default: `no`): Install a [systemd][systemd] service unit to start and stop Galaxy with the + system (and using the `systemctl` command). - `galaxy_manage_errordocs` (default: `no`): Install Galaxy-styled 413 and 502 HTTP error documents for nginx. Requires write privileges for the nginx error document directory. [client-build]: https://github.com/galaxyproject/galaxy/blob/dev/client/README.md#complete-client-build +[systemd]: https://www.freedesktop.org/wiki/Software/systemd/ **Galaxy code and configuration** @@ -323,6 +336,23 @@ The role needs to perform tasks as different users depending on which features y connecting to the target host. By default, the role will use `become` (i.e. sudo) to perform tasks as the appropriate user if deemed necessary. Overriding this behavior is discussed in the [defaults file][defaults]. +**systemd** + +[systemd][systemd] is the standard system init daemon on most modern Linux flavors (and all of the ones supported by +this role). If `galaxy_manage_systemd` is enabled, a `galaxy` service will be configured in systemd to run Galaxy. This +service will be automatically started and configured to start when your system boots. You can control the Galaxy +service with the `systemctl` utility as the `root` user or with `sudo`: + +```console +# systemctl start galaxy # start galaxy +# systemctl reload galaxy # attempt a "graceful" reload +# systemctl restart galaxy # perform a hard restart +# systemctl stop galaxy # stop galaxy +``` + +You can use systemd user mode if you do not have root privileges on your system by setting `galaxy_systemd_root` to +`false`. Add `--user` to the `systemctl` commands above to interact with systemd in user mode: + **Error documents** - `galaxy_errordocs_dir`: Install Galaxy-styled HTTP 413 and 502 error documents under this directory. The 502 message @@ -334,9 +364,6 @@ user if deemed necessary. Overriding this behavior is discussed in the [defaults **Miscellaneous options** -- `galaxy_restart_handler_name`: The role doesn't restart Galaxy since it doesn't control how Galaxy is started and - stopped. Because of this, you can write your own restart handler and inform the role of your handler's name with this - variable. See the examples - `galaxy_admin_email_to`: If set, email this address when Galaxy has been updated. Assumes mail is properly configured on the managed host. - `galaxy_admin_email_from`: Address to send the aforementioned email from. @@ -398,7 +425,6 @@ Install Galaxy as per the current production server best practices: galaxy_user: galaxy galaxy_privsep_user: gxpriv galaxy_group: galaxy - galaxy_restart_handler_name: Restart Galaxy postgresql_objects_users: - name: galaxy password: null @@ -453,6 +479,7 @@ Install Galaxy as per the current production server best practices: supervisorctl: name: galaxy state: restarted + listen: restart galaxy ``` License diff --git a/defaults/main.yml b/defaults/main.yml index 654c85e..6e129cc 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -302,19 +302,17 @@ galaxy_client_build_steps: - stageLibs - plugins -# Restart handler is already set if using the systemd options in this role, otherwise you need to define one yourself -galaxy_restart_handler_name: "{{ 'galaxy ' ~ galaxy_systemd_mode ~ ' restart' if galaxy_manage_systemd else 'default restart galaxy handler' }}" - # # systemd options # # Currently `mule` (aka uWSGI) and `gravity` (runs Galaxy 22.01+ under gunicorn) are supported -galaxy_systemd_mode: mule +galaxy_systemd_mode: "{{ 'mule' if __galaxy_major_version is version('22.05', '<') else 'gravity' }}" # Control whether the systemd service unit is installed/controlled as root or the Galaxy user galaxy_systemd_root: true +# The command that systemd will run to start Galaxy, depends on galaxy_systemd_mode or override galaxy_systemd_command: "{{ __galaxy_systemd_command[galaxy_systemd_mode] }}" __galaxy_systemd_command: mule: "{{ galaxy_venv_dir }}/bin/uwsgi {{ '--yaml' if galaxy_config_style in ('yaml', 'yml') else '--ini' }} {{ galaxy_config_file }}" diff --git a/handlers/main.yml b/handlers/main.yml index b6cf61b..a952f88 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -1,37 +1,33 @@ --- # defaults file for galaxyproject.galaxy -- name: default restart galaxy handler - debug: - msg: "RESTARTER NOT IMPLEMENTED - Please restart Galaxy manually. You can define your own handler and enable it with `galaxy_restart_handler_name`" - -- name: daemon reload +- name: systemd daemon reload systemd: daemon_reload: yes scope: "{{ galaxy_systemd_root | ternary(omit, 'user') }}" -- name: galaxy mule start +- name: galaxy systemd start systemd: name: galaxy.service state: started scope: "{{ galaxy_systemd_root | ternary(omit, 'user') }}" + when: "galaxy_systemd_mode == 'gravity'" + listen: "start galaxy" - name: galaxy mule restart systemd: name: galaxy.service state: restarted scope: "{{ galaxy_systemd_root | ternary(omit, 'user') }}" - -- name: galaxy gravity start - systemd: - name: galaxy.service - state: started - scope: "{{ galaxy_systemd_root | ternary(omit, 'user') }}" + when: "galaxy_systemd_mode == 'mule'" + listen: "restart galaxy" - name: galaxy gravity restart command: "{{ galaxy_venv_dir }}/bin/galaxyctl graceful" environment: GRAVITY_STATE_DIR: "{{ galaxy_gravity_state_dir }}" + when: "galaxy_systemd_mode == 'gravity'" + listen: "restart galaxy" - name: galaxyctl update command: "{{ galaxy_venv_dir }}/bin/galaxyctl update" diff --git a/tasks/clone.yml b/tasks/clone.yml index db5a532..e288170 100644 --- a/tasks/clone.yml +++ b/tasks/clone.yml @@ -15,7 +15,7 @@ diff: "{{ galaxy_diff_mode_verbose }}" register: __galaxy_git_update_result notify: - - "{{ galaxy_restart_handler_name }}" + - restart galaxy - name: Report Galaxy version change debug: diff --git a/tasks/main.yml b/tasks/main.yml index 3a5105f..0b38f05 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -134,9 +134,9 @@ tags: - galaxy_manage_gravity -- name: Include systemd unit setup tasks (Mules) +- name: Include systemd unit setup tasks (Galaxy) include_tasks: - file: systemd-mule.yml + file: systemd-galaxy.yml apply: tags: galaxy_manage_systemd when: galaxy_manage_systemd and galaxy_systemd_mode in ["mule", "gravity"] diff --git a/tasks/static_setup.yml b/tasks/static_setup.yml index e714e44..7a7cf81 100644 --- a/tasks/static_setup.yml +++ b/tasks/static_setup.yml @@ -16,7 +16,7 @@ mode: "{{ galaxy_config_perms }}" with_items: "{{ galaxy_config_files }}" notify: - - "{{ galaxy_restart_handler_name }}" + - restart galaxy - name: Install additional Galaxy config files (template) template: @@ -26,7 +26,7 @@ mode: "{{ galaxy_config_perms }}" with_items: "{{ galaxy_config_templates }}" notify: - - "{{ galaxy_restart_handler_name }}" + - restart galaxy - name: Install local tools copy: @@ -128,7 +128,7 @@ mode: "{{ galaxy_config_perms }}" notify: - galaxyctl update - - "{{ galaxy_restart_handler_name }}" + - restart galaxy remote_user: "{{ galaxy_remote_users.privsep | default(__galaxy_remote_user) }}" become: "{{ true if galaxy_become_users.privsep is defined else __galaxy_become }}" diff --git a/tasks/systemd-mule.yml b/tasks/systemd-galaxy.yml similarity index 76% rename from tasks/systemd-mule.yml rename to tasks/systemd-galaxy.yml index c9b5250..c3548e5 100644 --- a/tasks/systemd-mule.yml +++ b/tasks/systemd-galaxy.yml @@ -3,6 +3,10 @@ - name: Manage Paths block: + - name: Ensure Galaxy version is set + include_tasks: _inc_galaxy_version.yml + when: __galaxy_major_version is undefined + - name: Deploy Galaxy Unit template: owner: "{{ galaxy_systemd_root | ternary('root', omit) }}" @@ -11,10 +15,11 @@ src: systemd/galaxy.service.j2 dest: "{{ galaxy_systemd_root | ternary('/etc/systemd/system/', ('~' ~ __galaxy_user_name ~ '/.config/systemd/user') | expanduser) }}/galaxy.service" notify: - - daemon reload - - "{{ galaxy_restart_handler_name }}" + - systemd daemon reload + - start galaxy + - restart galaxy - - name: Enable Galaxy Unit + - name: Enable Galaxy service unit systemd: name: galaxy.service enabled: yes From 78a773d357e656fb5b89f01e144747dae4d822b3 Mon Sep 17 00:00:00 2001 From: Nate Coraor Date: Fri, 22 Apr 2022 12:26:58 -0400 Subject: [PATCH 07/10] Update minimum (and test) version of Ansible to 2.10 --- .github/workflows/ci.yml | 2 +- meta/main.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b5bf84f..677237b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: - name: Install dependencies run: | sudo apt-get install git python3 python3-virtualenv - pip3 install 'ansible<2.10' + pip3 install 'ansible<2.11' printf '[defaults]\nroles_path = ../\ninterpreter_python = /usr/bin/python3' > ansible.cfg - name: Run Test diff --git a/meta/main.yml b/meta/main.yml index 5d2963c..5311f18 100644 --- a/meta/main.yml +++ b/meta/main.yml @@ -6,7 +6,7 @@ galaxy_info: description: Install and manage a Galaxy (http://galaxyproject.org/) server. company: The Galaxy Project license: AFL v3.0 - min_ansible_version: 2.7 + min_ansible_version: 2.10 github_branch: main platforms: - name: EL From 41c912061d750c931e63cad2beb1ab3ddcd73c7e Mon Sep 17 00:00:00 2001 From: Nate Coraor Date: Fri, 22 Apr 2022 13:30:59 -0400 Subject: [PATCH 08/10] Conditional galaxy_manage_gravity based on version --- defaults/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/defaults/main.yml b/defaults/main.yml index 6e129cc..6b1bf19 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -19,7 +19,7 @@ galaxy_fetch_dependencies: yes galaxy_build_client: yes galaxy_manage_errordocs: no galaxy_backup_configfiles: yes -galaxy_manage_gravity: yes +galaxy_manage_gravity: "{{ false if __galaxy_major_version is version('22.05', '<') else true }}" galaxy_manage_systemd: no # For Galaxy galaxy_manage_systemd_reports: no # For Reports From 32501b17c68570a640705b78bead9bf7943656f9 Mon Sep 17 00:00:00 2001 From: Nate Coraor Date: Fri, 22 Apr 2022 13:50:23 -0400 Subject: [PATCH 09/10] Test against multiple versions --- .github/workflows/ci.yml | 7 ++++++- tests/test_playbook.yml | 3 +++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 677237b..955a803 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,6 +5,11 @@ on: [pull_request] jobs: setup: + strategy: + matrix: + galaxy-version: + - 21.01 + - 22.01 runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v2 @@ -20,7 +25,7 @@ jobs: - name: Run Test run: | export ANSIBLE_STDOUT_CALLBACK=yaml - ansible-playbook -i "localhost, " -c local tests/test_playbook.yml + ansible-playbook -i "localhost, " -c local tests/test_playbook.yml -e "galaxy_commit_id=release_${{ matrix.galaxy-version }}" systemctl status galaxy || true journalctl -u galaxy sleep 10 diff --git a/tests/test_playbook.yml b/tests/test_playbook.yml index 13da508..a6b9a98 100644 --- a/tests/test_playbook.yml +++ b/tests/test_playbook.yml @@ -13,6 +13,9 @@ galaxy_manage_download: no galaxy_manage_existing: no galaxy_manage_systemd: yes + # role default is < 22.05 + galaxy_manage_gravity: "{{ false if __galaxy_major_version is version('22.01', '<') else true }}" + galaxy_systemd_mode: "{{ 'mule' if __galaxy_major_version is version('22.01', '<') else 'gravity' }}" galaxy_config_style: yaml galaxy_layout: root-dir galaxy_root: /srv/galaxy From c5bb3457acdfcad48cbb93226779828c9c4dae7e Mon Sep 17 00:00:00 2001 From: Nate Coraor Date: Tue, 17 May 2022 10:21:31 +0200 Subject: [PATCH 10/10] Disable conda auto init in test --- tests/test_playbook.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_playbook.yml b/tests/test_playbook.yml index a6b9a98..010d0cd 100644 --- a/tests/test_playbook.yml +++ b/tests/test_playbook.yml @@ -26,6 +26,7 @@ galaxy_config: galaxy: database_connection: sqlite:///{{ galaxy_mutable_data_dir }}/universe.sqlite + conda_auto_init: false # needed because we've disabled facts ansible_user_uid: "{{ lookup('env', 'UID') }}" ansible_user_id: "{{ lookup('env', 'USER') }}"