From cb8a691183708f84cedd00a5dcf8878852836e29 Mon Sep 17 00:00:00 2001 From: Piotr Konopka Date: Mon, 5 May 2025 14:57:32 +0200 Subject: [PATCH] remove the obsolete prototype code --- fpctl/README.md | 268 ---- fpctl/src/TODO.md | 24 - fpctl/src/fpctl | 246 ---- fpctl/src/fpctl.py | 1127 ----------------- fpctl/systemd/system/README.md | 3 - .../system/flpprototype-qcchecker.service.j2 | 11 - .../system/flpprototype-qcchecker@.service.j2 | 13 - .../system/flpprototype-qctask.service.j2 | 13 - .../system/flpprototype-qctask@.service.j2 | 15 - .../system/flpprototype-readout.service.j2 | 10 - .../system/flpprototype-readout@.service.j2 | 10 - fpctl/systemd/system/hugetlbfs.service.j2 | 9 - hacking/example-config.yaml | 62 - 13 files changed, 1811 deletions(-) delete mode 100644 fpctl/README.md delete mode 100644 fpctl/src/TODO.md delete mode 100755 fpctl/src/fpctl delete mode 100755 fpctl/src/fpctl.py delete mode 100644 fpctl/systemd/system/README.md delete mode 100644 fpctl/systemd/system/flpprototype-qcchecker.service.j2 delete mode 100644 fpctl/systemd/system/flpprototype-qcchecker@.service.j2 delete mode 100644 fpctl/systemd/system/flpprototype-qctask.service.j2 delete mode 100644 fpctl/systemd/system/flpprototype-qctask@.service.j2 delete mode 100644 fpctl/systemd/system/flpprototype-readout.service.j2 delete mode 100644 fpctl/systemd/system/flpprototype-readout@.service.j2 delete mode 100644 fpctl/systemd/system/hugetlbfs.service.j2 delete mode 100644 hacking/example-config.yaml diff --git a/fpctl/README.md b/fpctl/README.md deleted file mode 100644 index 30c8b3490..000000000 --- a/fpctl/README.md +++ /dev/null @@ -1,268 +0,0 @@ -# Control - -This repository hosts those parts of the control system for the September 2017 TPC test that aren't already kept in system-configuration. - -## Automatic setup with `fpctl` - -`fpctl` is an FLP prototype setup and control utility. Its goal is to make it easy -to deploy, configure and control an FLP prototype testing stack on one or more -target machines. - -`fpctl` requires CERN CentOS 7, with or without Kerberos authentication. If your source or target systems are not set up with CERN Kerberos authentication, you must enable passwordless login via public key authentication (see [Authentication on the target system](README.md#authentication-on-the-target-system)). - -Currently, in order to install `fpctl` you need access to certain git repositories on CERN GitLab. To gain access, you need to join [the alice-o2-detector-teams e-group](https://e-groups.cern.ch/e-groups/EgroupsSearch.do?searchValue=alice-o2-detector-teams). - -Set the `fpctl` install path and get `fpctl`: -``` -export FPCTL_ROOT_DIR=~/.local -mkdir -p $FPCTL_ROOT_DIR/bin -curl -o $FPCTL_ROOT_DIR/bin/fpctl https://raw.githubusercontent.com/AliceO2Group/Control/master/fpctl/src/fpctl -chmod +x $FPCTL_ROOT_DIR/bin/fpctl -export PATH="$FPCTL_ROOT_DIR/bin:$PATH" -``` - -Add `fpctl` binary directory to PATH (optional but useful): -``` -echo -e '\nexport PATH='"$FPCTL_ROOT_DIR"'/bin:$PATH\n' >> ~/.bashrc -``` - -Setup `fpctl` (if you don't run this it will run anyway the first time you use `fpctl` for some other operation): -``` -fpctl setup -``` -You should now have some repositories in `~/.local/share/fpctl` (or some other directory, depending on your `FPCTL_ROOT_DIR`). The setup routine also takes care of installing things like git and Ansible on your system. - -If you want to deploy FLP prototype on a remote system, you should create an Ansible inventory file in `~/.config/fpctl/inventory`. Otherwise, if you simply wish to deploy all the FLP prototype software on your local machine, you can proceed immediately: -``` -fpctl deploy -``` -If you haven't provided an inventory file, `fpctl` will offer to create one for you. `fpctl` may also offer to configure passwordless sudo, depending on your configuration. The deployment operation may take a while. You will see some Ansible output as everything is installed and configured. - -Start/stop all the tasks (`fpctl` and Ansible take care of doing this in the correct order): -``` -fpctl start -fpctl stop -``` - -You may also choose to only control one of the tasks: -``` -fpctl start readout -fpctl start qctask -fpctl start qcchecker -``` -An instruction like these previous three will start a given task on all the inventory items assigned to it. For instance, if you have two hosts under `[flp-readout]` in your inventory, `fpctl start readout` will start two processes, one for each machine. Similarly, `fpctl stop readout` will stop them all. - -Occasionally you might want to run `fpctl update` to pull any changes to the deployment data and to the `fpctl` tool itself. - -To deploy any configuration changes to your FLP prototype systems without reinstalling everything, run: -``` -fpctl configure -``` -It is a good idea to then restart all the FLP prototype processes to apply the new configuration. - -For more information, check `fpctl --help`. - -## fpctl Configuration and Inventory - -`fpctl` uses standard Ansible inventory files. The default inventory file path is `~/.config/fpctl/inventory`. An alternative inventory file can be passed to `fpctl` with the option `-i` or `--inventory`. A `fpctl`/Ansible inventory file must provide one or more hosts for each of the following five machine groups: - -- `flp-readout` -- `qc-task` -- `qc-checker` -- `qc-repository` -- `infologger-server` - -A host can belong to more than one group, and in fact, the default inventory that `fpctl deploy` can generate automatically looks like this: - -``` -[flp-readout] -localhost ansible_connection=local -[qc-task] -localhost ansible_connection=local -[qc-checker] -localhost ansible_connection=local -[qc-repository] -localhost ansible_connection=local -[infologger-server] -localhost ansible_connection=local -``` - -The whitespace-separated key-value pairs after the hostname are per-host variables. These can override Ansible settings, as well as any variable internally used by `fpctl`'s Ansible playbooks. For example: - -- `ansible_become_method=ksu` - use `ksu` instead of `sudo` for acquiring privileges on the target system (useful on Kerberos setups); -- `small_hugepages_count`/`large_hugepages_count` - number of hugepages allocated for the readout process; -- `flpprototype_qc_mysql_root_password` - the MariaDB root password of an existing MariaDB instance for the `qc-repository` (only necessary if a password exists), -- `ansible_connection=local` - run everything locally instead of using SSH (only applies to `localhost`) - -Here's an example of an inventory file with some remote machines, including two readout machines, one QC checker machine, and one machine with a QC task and a QC repository: - -``` -[flp-readout] -my-readout-1.cern.ch ansible_become_method=ksu small_hugepages_count=256 -my-readout-2.cern.ch ansible_become_method=ksu small_hugepages_count=256 -[qc-task] -my-qctask.cern.ch ansible_become_method=ksu -[qc-checker] -my-qcchecker.cern.ch -[qc-repository] -my-qctask.cern.ch ansible_become_method=ksu -[infologger-server] -my-infologger.cern.ch -``` - -For more information on inventory files, see [the Ansible Inventory documentation](http://docs.ansible.com/ansible/intro_inventory.html). - -## Quick start manual setup with Ansible - -Assuming a default CC7 setup with Kerberos authentication. If your source or target systems are **not** set up with CERN Kerberos authentication, you must enable passwordless login via public key authentication (see [Authentication on the target system](#authentication-on-the-target-system)). - -Create the inventory file: -``` -echo -e "[flp-readout]\nlocalhost ansible_connection=local\n[qc-task]\nlocalhost ansible_connection=local\n[qc-checker]\nlocalhost ansible_connection=local\n[qc-repository]\nlocalhost ansible_connection=local\n[infologger-server]\nlocalhost ansible_connection=local\n" > myinventory -``` -Replace `localhost` with the hostname of your target machine (and remove the `ansible_connection=local` variable which only applies to `localhost`). - -Install Ansible, clone the repos and deploy: -``` -sudo yum -y install git ansible -git clone https://github.com/AliceO2Group/Control.git -git clone https://gitlab.cern.ch/AliceO2Group/system-configuration.git -sudo sed -i "/^# control_path_dir =/s/.*/control_path_dir = \/tmp\/.ansible\/cp/" /etc/ansible/ansible.cfg -sudo sed -i "/^#host_key_checking =/s/.*/host_key_checking = False/" /etc/ansible/ansible.cfg -cd system-configuration/ansible -ansible-playbook -i ../../myinventory -s site.yml -e "flpprototype_systemd=../../Control/fpctl/systemd/system" -``` -The `git clone` statements above assume git over HTTPS. If you use SSH public key authentication with GitHub and/or GitLab, you may do the following instead: -``` -git clone git@github.com:AliceO2Group/Control.git -git clone ssh://git@gitlab.cern.ch:7999/AliceO2Group/system-configuration.git -``` - -## Full guide for Ansible deployment - -### Setting up Ansible - -To use this, you need to clone this repo, as well as the system-configuration repo which contains the Ansible configuration. - -``` -$ sudo yum install git ansible -$ git clone git@github.com:AliceO2Group/Control.git -$ git clone ssh://git@gitlab.cern.ch:7999/AliceO2Group/system-configuration.git -``` - -You should also create an inventory file which points to one or more fresh systems. Here's what an inventory file should look like: -``` -[flp-readout] -my-readout-testing-machine.cern.ch -my-other-readout-testing-machine.cern.ch -[qc-task] -... -[qc-checker] -... -[qc-repository] -... -[infologger-server] -... -``` - -The target system should accept passwordless SSH authentication (Kerberos, public key). This guide assumes that the target system is a clean CC7 instance on CERN OpenStack. - -If you are using Kerberos login for Ansible (default if you run CC7 with your CERN user account), you must also add an option in your inventory file to do passwordless privilege escalation with `ksu` instead of `sudo`, as the latter does not support `NOPASSWD` with Kerberos. - -``` -[flp-readout] -cc7-testing-machine.cern.ch ansible_become_method=ksu -[qc-task] -cc7-testing-machine.cern.ch ansible_become_method=ksu -[qc-checker] -cc7-testing-machine.cern.ch ansible_become_method=ksu -[qc-repository] -cc7-testing-machine.cern.ch ansible_become_method=ksu -[infologger-server] -cc7-testing-machine.cern.ch ansible_become_method=ksu -``` - -### Ansible and AFS - -If your home directory is *not* on AFS, skip to the next section. - -If you are running a default CC7 configuration with your home directory on AFS on your control machine, you must change the `control_path_dir` value in `/etc/ansible/ansible.cfg` to **any path that is not on AFS**. For instance, `/tmp/.ansible/cp` is a good value that's already suggested in the configuration file, so all you have to do is uncomment it. - -The reason for this is that Ansible uses SSH multiplexing to avoid creating new TCP connections for each SSH session to a target machine after the first one. This improves performance, but requires a socket file, which Ansible places in `~/.ansible/cp` by default. AFS doesn't like this, and Ansible's SSH fails with an "Operation not permitted" error. - -For more information, see https://en.wikibooks.org/wiki/OpenSSH/Cookbook/Multiplexing#Errors_Preventing_Multiplexing. - -### Authentication on the target system - -If you are running CC7 with your CERN user account and Kerberos authentication on both your system and the target system, skip to the next section (but be sure to set `ksu` as privilege escalation tool in your inventory). - -Before running Ansible commands on a target system, a way is needed for Ansible to log in and perform tasks which usually require root privileges. As far as the target system is concerned, you should make sure that: -* either the target system allows SSH login as root (configuration file `/etc/ssh/sshd_config`), accepts public key authentication for root, and Ansible is run as root (by appending `-u root` to Ansible commands); OR -* the target system accepts public key authentication for the unprivileged user, and this user is `sudo`-enabled with `NOPASSWD` on the target system. - -Ideally one would use an unprivileged user, and keep SSH root login disabled (default on CC7). If this is the case, the user on the target system must be in the group `wheel`. The command `# gpasswd -a username wheel` adds a user to the `wheel` group. To allow passwordless `sudo` the line `%wheel ALL=(ALL) NOPASSWD: ALL` should be present and uncommented in the sudoers configuration file. To check this, run `# visudo` as root on the target system. - -To enable public key authentication on the target system, the following steps are needed. - -1) Make sure you have a public key on the control machine (i.e. your machine), it is usually called `~/.ssh/id_rsa.pub` or `~/.ssh/id_dsa.pub`. If not, you can create one with `ssh-keygen`. -2) Add the contents of your `id_rsa.pub` (or similar) to `~/.ssh/authorized_keys` *on the target system*. To do that, either SSH into it and copy the contents, or run `ssh-copy-id your_username@target_hostname` on the control machine. -3) Since you are now relying on SSH public key authentication, you must make sure that your inventory file does not contain `ansible_become_method=ksu`, as this only works with Kerberos. -4) You must also make sure that the unprivileged user on the target system is a member of the `wheel` group (`# gpasswd -a username wheel`) and that the line `%wheel ALL=(ALL)       NOPASSWD: ALL` is uncommented in the `sudoers` file (editable with `visudo`). - -For more information on SSH public key authentication, see https://help.ubuntu.com/community/SSH/OpenSSH/Keys. - -### Running ansible-playbook - -Assuming the current directory is the one with Ansible's `site.yml` (directory `ansible` in the system-configuration repository) and assuming this repository (Control) is cloned at `~/Control`, this is the single step for deployment, configuration and execution (adjust the paths as needed): - -``` -$ ansible-playbook -i path/to/inventory/file -s site.yml -e "flpprototype_systemd=~/Control/fpctl/systemd/system" -``` - -This will install `alisw-flpproto` with all its dependencies on the machines from the relevant inventory file and deploy the dummy configuration files. It will also deploy some Systemd units for readout and QC. - -Add `-t `*`tag`*` ` where *`tag`* is `installation`, `configuration` or `execution` to only run one of these phases. - -### Things to do on the target machine - -View the logs for a service: - -`$ sudo journalctl -u flpprototype-readout` - -`$ sudo journalctl -u flpprototype-qctask` - -`$ sudo journalctl -u flpprototype-qcchecker` - -Control the service: - -`$ sudo systemctl start flpprototype-readout` - -`$ sudo systemctl status flpprototype-readout` - -`$ sudo systemctl stop flpprototype-readout` - -### Parametrized services - -Systemd templates allow the user to pass arguments when starting a unit. - -Start a readout service with a specific configuration (by default, configuration files are deployed to `/etc/flpprototype.d`): - -`$ sudo systemctl start flpprototype-readout@configDummy` - -The QC task service is similar, but it requires two parameters (the task name and the configuration file name): - -`$ sudo systemctl start flpprototype-qctask@myTask_1@example-default` - -### Things to do on the controller machine - -Query or control the flpprototype-readout Systemd service state on all machines without going through the Ansible role: - -`$ ansible -b -i myinventoryfile all -a "systemctl start flpprototype-readout"` - -`$ ansible -b -i myinventoryfile all -a "systemctl status flpprototype-readout"` - -`$ ansible -b -i myinventoryfile all -a "systemctl stop flpprototype-readout"` - -Example with QC task, parametrized: - -`$ ansible -b -i myinventoryfile all -a "systemctl status flpprototype-qctask@myTask_1@example-default"` diff --git a/fpctl/src/TODO.md b/fpctl/src/TODO.md deleted file mode 100644 index 94de1e339..000000000 --- a/fpctl/src/TODO.md +++ /dev/null @@ -1,24 +0,0 @@ -# FlpPrototype control wrapper design - -* Initial instructions for installing the script would include wget bash script into a bin - path (like /usr/local/bin), or into ~/bin and adding this to PATH. -* Initial shell script fpctl: if python3 exists and if repos are set up, call - ~/.local/fpctl/Control/fpctl.py. Therefore, fpctl is always the entry point. - Else, if any of the requirements for running the actual Python wrapper are not met, do - stuff like installing python34, git, ansible, etc., git clone Control and - system-configuration, creating ~/.config/fpctl, ... -* Instruct people to add their SSH keys to gitlab.cern.ch in order for the script to work. - On error bail out (this should only happen on systems other than CC7). -* The inventory file is assumed to be ~/.config/fpctl/inventory, this can be overridden - as -i /path/to/inventory. -* Syntax ideas: - * fpctl update/up - * fpctl deploy/de - * fpctl configure/co - * fpctl run [machinename] [command] // wrapper for ansible interactive command - * fpctl start [taskname] - * fpctl status [taskname] - * fpctl stop [taskname] - * fpctl log [taskname] - * fpctl help -* Also do documentation for inventory. diff --git a/fpctl/src/fpctl b/fpctl/src/fpctl deleted file mode 100755 index 170c54824..000000000 --- a/fpctl/src/fpctl +++ /dev/null @@ -1,246 +0,0 @@ -#!/usr/bin/env bash - -FPCTL_CONFIG_DIR="$HOME/.config/fpctl" -if [[ -z ${FPCTL_ROOT_DIR} ]]; then - FPCTL_ROOT_DIR="$HOME/.local" -fi -FPCTL_DATA_DIR="$FPCTL_ROOT_DIR/share/fpctl" - -C_WARN="\033[1;33m==> WARNING: \033[0m" -C_YELL="\033[1;33m==> \033[0m" -C_QUEST=$C_YELL -C_ERR="\033[1;31m==> ERROR: \033[0m" -C_RED="\033[1;31m==> \033[0m" -C_MSG="\033[1;32m==> \033[0m" -C_ITEM="\033[1;34m -> \033[0m" - -bail() -{ - echo -e "${C_ERR}$1" - echo -e "${C_RED}fpctl will now quit." -} - -message() -{ - echo -e "${C_MSG}$1" -} - -check_dependencies() -{ - message "Checking dependencies..." - which pip3 &>/dev/null - HAS_PYTHON3="$?" - - which git &>/dev/null - HAS_GIT="$?" - - which ansible &>/dev/null - HAS_ANSIBLE="$?" - - which ssh &>/dev/null - HAS_OPENSSH="$?" - - python3 -c "import colorama" &>/dev/null - HAS_COLORAMA="$?" - - python3 -c "import terminaltables" &>/dev/null - HAS_TERMINALTABLES="$?" - - if [[ "$HAS_PYTHON3" != "0" || - "$HAS_GIT" != "0" || - "$HAS_ANSIBLE" != "0" || - "$HAS_OPENSSH" != "0" || - "$HAS_COLORAMA" != "0" || - "$HAS_TERMINALTABLES" != "0" ]]; then - message "Installing dependencies..." - sudo yum -y -q install python34 python34-pip ansible git openssh-clients - if [[ "$?" != 0 ]]; then - bail $'could not install dependencies. To install the required packages manually, try running the following command \033[1mas root\033[0m:\nyum install python34 ansible git openssh-clients' - exit 5 - fi - sudo su -c "yes|pip3 install colorama terminaltables" - if [[ "$?" != 0 ]]; then - bail $'could not install dependencies. To install the required packages manually, try running the following command \033[1mas root\033[0m:\npip3 install colorama terminaltables' - exit 5 - fi - fi -} - -configure_ansible() -{ - /usr/bin/cp -f /etc/ansible/ansible.cfg $FPCTL_CONFIG_DIR - sed -i "/^# control_path_dir =/s/.*/control_path_dir = \/tmp\/.ansible\/cp/" $FPCTL_CONFIG_DIR/ansible.cfg - sed -i "/^#host_key_checking =/s/.*/host_key_checking = False/" $FPCTL_CONFIG_DIR/ansible.cfg - # NOTE: the following line enables SSH pipelining to improve performance. This is ok - # on CC7 since its sudoers configuration does not contain "requiretty", but - # might fail miserably on other target distros. - sed -i "/^#pipelining =/s/.*/pipelining = True/" $FPCTL_CONFIG_DIR/ansible.cfg - # NOTE: another potential performance gain. With this line we ask Ansible to keep - # idle SSH connections active for 3 minutes before closing them. - sed -i "/^connect_timeout =/s/.*/connect_timeout = 180/" $FPCTL_CONFIG_DIR/ansible.cfg - sed -i "\|^#fact_caching =|s|.*|fact_caching = jsonfile\nfact_caching_connection = $FPCTL_DATA_DIR/ansible_cache|" $FPCTL_CONFIG_DIR/ansible.cfg -} - -setup() -{ - # (1) SUPPORTED OS - message "Checking for supported operating system..." - uname -r | grep -q el7 - IS_KERNEL_EL7="$?" - - lsb_release -d | grep -q "CentOS Linux release 7" - IS_LSB_CENTOS7="$?" - - if [[ ! ($IS_KERNEL_EL7 && $IS_LSB_CENTOS7) ]]; then - echo -e "${C_WARN}unsupported operating system detected." - echo -e "${C_YELL}The reference platform for fpctl is CERN CentOS 7. fpctl will continue, but if issues arise you're on your own." - fi - - # (2) DEPENDENCIES - check_dependencies - - # (3) DIRECTORIES - message "Setting up directories..." - E_BAD_PATH=3 - if [[ ! -d $FPCTL_CONFIG_DIR ]]; then - message "Creating configuration directory at $FPCTL_CONFIG_DIR..." - mkdir -p $FPCTL_CONFIG_DIR - if [[ "$?" != 0 ]]; then - bail "cannot create fpctl configuration directory: $FPCTL_CONFIG_DIR." - exit $E_BAD_PATH - fi - fi - if [[ ! -w $FPCTL_CONFIG_DIR ]]; then - bail "configuration directory $FPCTL_CONFIG_DIR is not writable." - exit $E_BAD_PATH - fi - - if [[ ! -d $FPCTL_DATA_DIR ]]; then - message "Creating data directory at $FPCTL_DATA_DIR..." - mkdir -p $FPCTL_DATA_DIR - if [[ "$?" != 0 ]]; then - bail "cannot create fpctl data directory: $FPCTL_DATA_DIR." - exit $E_BAD_PATH - fi - fi - if [[ ! -w $FPCTL_DATA_DIR ]]; then - bail "data directory $FPCTL_DATA_DIR is not writable." - exit $E_BAD_PATH - fi - - configure_ansible - - # (4) GIT REPOSITORIES - message "Fetching fpctl data and system configuration..." - FPCTL_CONTROL_REPOSITORY_SSH="git@github.com:AliceO2Group/Control.git" - FPCTL_CONTROL_REPOSITORY_HTTPS="https://github.com/AliceO2Group/Control.git" - FPCTL_CONTROL_REPOSITORY_NAME="GitHub" - FPCTL_ANSIBLE_REPOSITORY_SSH="ssh://git@gitlab.cern.ch:7999/AliceO2Group/system-configuration.git" - FPCTL_ANSIBLE_REPOSITORY_HTTPS="https://gitlab.cern.ch/AliceO2Group/system-configuration.git" - FPCTL_ANSIBLE_REPOSITORY_NAME="CERN GitLab" - - git_clone() - { - SSH_URL="$1" - HTTPS_URL="$2" - KEYS_URL="$3" - DEST_PATH="$4" - REPO_PROVIDER="$5" - - if [[ -d "$DEST_PATH" ]]; then - while true; do - echo -ne "${C_QUEST}${DEST_PATH} already exists. Overwrite [y/n]?\n${C_QUEST}------------------------------------\n${C_QUEST}" - read yn - case $yn in - [Yy]* ) rm -rf "$DEST_PATH" &>/dev/null; break;; - [Nn]* ) message "Skipping repository setup..."; return 0;; - * ) echo -e "${C_QUEST}Please answer yes or no [y/n].";; - esac - done - fi - git clone "$SSH_URL" "$DEST_PATH" - if [[ "$?" != 0 ]]; then - echo -e "${C_WARN}cannot fetch system-configuration repository via SSH. Your SSH key must be listed on $KEYS_URL for this to work.\n${C_YELL}Falling back to HTTPS, you will be prompted for your $REPO_PROVIDER credentials." - git clone "$HTTPS_URL" "$DEST_PATH" - if [[ "$?" != 0 ]]; then - exit 4 - fi - fi - } - - git_clone $FPCTL_ANSIBLE_REPOSITORY_SSH $FPCTL_ANSIBLE_REPOSITORY_HTTPS "https://gitlab.cern.ch/profile/keys" "$FPCTL_DATA_DIR/system-configuration" "${FPCTL_ANSIBLE_REPOSITORY_NAME}" - if [[ "$?" != 0 ]]; then - bail "could not fetch git repository system-configuration. Please make sure that your CERN credentials are correct, and that you are a member of the alice-o2-detector-teams e-group (https://e-groups.cern.ch/e-groups/EgroupsSearch.do?searchValue=alice-o2-detector-teams)." - exit $? - fi - git_clone $FPCTL_CONTROL_REPOSITORY_SSH $FPCTL_CONTROL_REPOSITORY_HTTPS "https://github.com/settings/keys" "$FPCTL_DATA_DIR/Control" "${FPCTL_CONTROL_REPOSITORY_NAME}" - if [[ "$?" != 0 ]]; then - bail "could not fetch git repository Control. Please make sure that your GitHub credentials are correct." - exit $? - fi -} - -update() -{ - message "Updating fpctl..." - cd $FPCTL_DATA_DIR/Control && git pull --rebase - if [[ "$?" != 0 ]]; then - message "Cannot update git repository Control. Try running fpctl setup instead." - return 5 - fi - - message "Updating system configuration..." - cd $FPCTL_DATA_DIR/system-configuration && git pull --rebase - if [[ "$?" != 0 ]]; then - message "Cannot update git repository system-configuration. Try running fpctl setup instead." - return 5 - fi - - check_dependencies - - configure_ansible - - message "Finishing up..." - MYPATH=`readlink -f $0` - \cp -f $FPCTL_DATA_DIR/Control/fpctl/src/fpctl $MYPATH || true -} - - -if [[ "$1" == "setup" ]]; then - setup - STATUS="$?" - if [[ "$STATUS" == "0" ]]; then - echo -e "$FPCTL_ROOT_DIR" > "$FPCTL_CONFIG_DIR/.installed" - message "All done." - fi - exit $STATUS - -elif [[ "$1" == "update" || "$1" == "up" ]]; then - FPCTL_ROOT_DIR=$(head -n 1 "$FPCTL_CONFIG_DIR/.installed") - if [[ -z ${FPCTL_ROOT_DIR} ]]; then - FPCTL_ROOT_DIR="$HOME/.local" - fi - FPCTL_DATA_DIR="$FPCTL_ROOT_DIR/share/fpctl" - - update - STATUS="$?" - if [[ "$STATUS" == "0" ]]; then - echo -e "$FPCTL_ROOT_DIR" > "$FPCTL_CONFIG_DIR/.installed" - message "All done." - fi - exit $STATUS - -elif [[ ! -e "$FPCTL_CONFIG_DIR/.installed" ]]; then - message "fpctl configuration not found. Running first-run setup." - setup - STATUS="$?" - if [[ "$STATUS" == "0" ]]; then - echo -e "$FPCTL_ROOT_DIR" > "$FPCTL_CONFIG_DIR/.installed" - message "Setup done." - exec "$FPCTL_DATA_DIR/Control/fpctl/src/fpctl.py" "$@" - fi - exit $STATUS - -else - exec "$FPCTL_DATA_DIR/Control/fpctl/src/fpctl.py" "$@" -fi diff --git a/fpctl/src/fpctl.py b/fpctl/src/fpctl.py deleted file mode 100755 index 5500ce275..000000000 --- a/fpctl/src/fpctl.py +++ /dev/null @@ -1,1127 +0,0 @@ -#!/usr/bin/env python3 - -import argparse -import datetime -import errno -import getpass -import json -import logging -import os -import re -import subprocess -import sys -import time -from operator import itemgetter -from collections import OrderedDict - -try: - from colorama import Fore, Style - from terminaltables import SingleTable -except ImportError as e: - print('==> ERROR: cannot import a required Python module. Run fpctl setup to ensure ' - 'all dependencies are installed.') - print('Missing module: {}'.format(e.name)) - sys.exit(1) - - -FPCTL_CONFIG_DIR = os.path.expanduser('~/.config/fpctl') -FPCTL_ROOT_DIR = os.path.expanduser('~/.local') -with open(os.path.join(FPCTL_CONFIG_DIR, '.installed')) as f: - root_dir = f.readline().strip() - if (os.path.isdir(root_dir)): - FPCTL_ROOT_DIR = root_dir - else: - raise FileNotFoundError(errno.ENOENT, - os.strerror(errno.ENOENT), - root_dir) -FPCTL_DATA_DIR = os.path.expanduser(os.path.join(FPCTL_ROOT_DIR, 'share/fpctl')) -INVENTORY_READOUT_GROUP = 'flp-readout' -INVENTORY_QCTASK_GROUP = 'qc-task' -INVENTORY_QCCHECKER_GROUP = 'qc-checker' -INVENTORY_QCREPOSITORY_GROUP = 'qc-repository' -INVENTORY_INFOLOGGERSERVER_GROUP = 'infologger-server' -DEFAULT_INVENTORY_PATH = os.path.join(FPCTL_CONFIG_DIR, 'inventory') - -TARGET_GROUPS = ['flp-readout', 'qc-task', 'qc-checker'] -TASK_NAMES = ['readout', 'qctask', 'qcchecker'] - -C_WARN = Style.BRIGHT + Fore.YELLOW + '==> WARNING: ' + Style.RESET_ALL -C_YELL = Style.BRIGHT + Fore.YELLOW + '==> ' + Style.RESET_ALL -C_QUEST = C_YELL -C_ERR = Style.BRIGHT + Fore.RED + '==> ERROR: ' + Style.RESET_ALL -C_RED = Style.BRIGHT + Fore.RED + '==> ' + Style.RESET_ALL -C_MSG = Style.BRIGHT + Fore.GREEN + '==> ' + Style.RESET_ALL -C_ITEM_NO_PADDING = Style.BRIGHT + Fore.BLUE + '-> ' + Style.RESET_ALL -C_ITEM = ' ' + C_ITEM_NO_PADDING -BULLET = '\u25CF ' -ANSIBLE_SSH_DOCUMENTATION = 'https://github.com/AliceO2Group/Control/fpctl#authentication-on-the-target-system' - - -class Reprinter: - def __init__(self): - self.text = '' - - def moveup(self, lines): - for _ in range(lines): - sys.stdout.write("\x1b[A") - - def reprint(self, text): - # Clear previous text by overwritig non-spaces with spaces - self.moveup(self.text.count("\n")) - sys.stdout.write(re.sub(r"[^\s]", " ", self.text)) - - # Print new text - lines = min(self.text.count("\n"), text.count("\n")) - self.moveup(lines) - sys.stdout.write(text) - self.text = text - - -class Inventory: - def __init__(self, inventory_path): - self.inventory_path = inventory_path - self.inventory_file_lines = [] - self.hosts_cache_file_path = os.path.join(FPCTL_DATA_DIR, 'hosts_cache.json') - self.pubkey_file_path = '' - self.hosts_cache = dict() - self.SSH_DIR = os.path.join(os.path.expanduser('~'), '.ssh') - self.__init_cache() - - def __init_cache(self): - hosts_cache = dict() - if os.path.isfile(self.hosts_cache_file_path): - try: - with open(self.hosts_cache_file_path, 'r') as hosts_cache_file: - hosts_cache = json.load(hosts_cache_file) - except Exception as e: - print(C_WARN + 'A fpctl hosts cache exists but loading failed, so the ' + - 'cache will be overwritten. If you see this message more than ' + - 'once, try reinstalling fpctl.') - self.hosts_cache = hosts_cache - - def __write_cache(self): - try: - with open(self.hosts_cache_file_path, 'w') as hosts_cache_file: - json.dump(self.hosts_cache, hosts_cache_file) - except Exception as e: - print(C_WARN + 'Cannot write fpctl hosts cache. If you see this ' + - 'message more than once, try reinstalling fpctl.') - - def load(self): - output = subprocess.check_output(['ansible', - 'all', - '-i{}'.format(self.inventory_path), - '--list-hosts']) - inventory_hosts = output.decode(sys.stdout.encoding).splitlines() - inventory_hosts = inventory_hosts[1:] # we throw away the first line which is only a summary - self.inventory_hosts = [line.strip() for line in inventory_hosts] - - inventory_file_lines = [] - with open(self.inventory_path, 'r') as inventory_file: - inventory_file_lines = inventory_file.readlines() - - self.inventory_file_lines = inventory_file_lines - - if inventory_hosts != ['localhost']: - self.__check_for_ssh_keys() - - def check_hosts(self, force=False): - try: - self.__check_for_ssh_auth(force) - self.__check_for_sudo_nopasswd(force) - finally: - if self.hosts_cache: - self.__write_cache() - - def __check_for_ssh_keys(self): - self.force_deploy_ssh_keys = False - if not os.path.isdir(self.SSH_DIR): - self.force_deploy_ssh_keys = \ - query_yes_no('SSH configuration directory not found. fpctl needs ' - 'a public/private SSH key pair to operate on the ' - 'target machines. The SSH configuration directory, ' - 'as well as a key pair, can be created for you and ' - 'deployed on the target systems. Do you wish to ' - 'proceed?', default='yes') - if self.force_deploy_ssh_keys: - os.mkdir(self.SSH_DIR) - else: - print(C_RED + 'Since Ansible requires passwordless authentication on the target ' - 'hosts in order to work, fpctl cannot continue.\n' + C_RED + - 'Please see {} for instructions on how to ' - 'set up passwordless authentication for Ansible/fpctl.' - .format(ANSIBLE_SSH_DOCUMENTATION)) - self.__write_cache() - sys.exit(1) - - if self.force_deploy_ssh_keys: - self.__create_rsa_keypair() - return - - candidate_keyfiles = [['id_rsa.pub', 'id_rsa'], - ['id_dsa.pub', 'id_dsa']] - candidate_keyfiles = [[os.path.join(self.SSH_DIR, jtem) for jtem in item] for item in candidate_keyfiles] - for keypair in candidate_keyfiles: - if os.path.isfile(keypair[0]) and \ - os.path.isfile(keypair[1]): - self.pubkey_file_path = keypair[0] - print(C_MSG + 'Found SSH public/private key pair {0}/{1}.' - .format(os.path.basename(keypair[0]), - os.path.basename(keypair[1]))) - break - - if not self.pubkey_file_path: - self.force_deploy_ssh_keys = \ - query_yes_no('No suitable SSH public/private key pairs were found. ' - 'fpctl needs ' - 'a public/private SSH key pair to operate on the ' - 'target machines. The SSH configuration directory, ' - 'as well as a key pair, can be created for you and ' - 'deployed on the target systems. Do you wish to ' - 'proceed?', default='yes') - if self.force_deploy_ssh_keys: - self.__create_rsa_keypair() - else: - print(C_RED + 'Since Ansible requires passwordless authentication on the target ' - 'hosts in order to work, fpctl cannot continue.\n' + C_RED + - 'Please see {} for instructions on how to ' - 'set up passwordless authentication for Ansible/fpctl.' - .format(ANSIBLE_SSH_DOCUMENTATION)) - self.__write_cache() - sys.exit(1) - - def __create_rsa_keypair(self): - self.force_deploy_ssh_keys = True - rc = subprocess.call('ssh-keygen -t rsa -N "" -f id_rsa -q', - shell=True, - cwd=self.SSH_DIR) - if rc != 0: - print(C_ERR + 'Cannot create RSA key pair.') - self.__write_cache() - sys.exit(1) - - self.pubkey_file_path = os.path.join(self.SSH_DIR, 'id_rsa.pub') - - def __deploy_ssh_keys(self, hosts_that_cannot_ssh): - if not self.pubkey_file_path: - print(C_ERR + 'Cannot find SSH public key for deployment on target system.') - self.__write_cache() - sys.exit(1) - - for host_user_tuple in hosts_that_cannot_ssh: - ansible_user = host_user_tuple[1] - target_hostname = host_user_tuple[0] - password = getpass.getpass(prompt='[ssh] password for {0}@{1}: ' - .format(ansible_user, target_hostname)) - SCI_CALL = '/usr/bin/sshpass -p{3} /usr/bin/ssh-copy-id -i {0} {1}@{2}'.format( - self.pubkey_file_path, - ansible_user, - target_hostname, - password) - rc = subprocess.call(SCI_CALL, shell=True) - if rc != 0: - print(C_ERR + 'Cannot deploy SSH public key to target system.') - self.__write_cache() - sys.exit(1) - - def __check_for_ssh_auth(self, force=False): - hosts_that_cannot_ssh = [] - has_localhosts = False - - result = [] - for target_hostname in self.inventory_hosts: - ansible_user = os.environ.get('USER') - for line in self.inventory_file_lines: - if line.startswith(target_hostname) and 'ansible_user='in line: - splitline = line.split(' ') - for word in splitline: - if word.startswith('ansible_user='): - ansible_user = word.strip()[13:] - break # we found an ansible_user override, so we break and go on - - if not force and \ - target_hostname in self.hosts_cache and \ - 'auth_methods' in self.hosts_cache[target_hostname] and \ - self.hosts_cache[target_hostname]['auth_methods'] and \ - 'ansible_user' in self.hosts_cache[target_hostname] and \ - self.hosts_cache[target_hostname]['ansible_user'] == ansible_user: - result.append({'host': target_hostname, - 'auth': self.hosts_cache[target_hostname]['auth_methods']}) - continue - - # HACK: we check if there's an ansible_user specified for this hostname in the - # inventory file. This should be replaced with ansible-python binding. - if target_hostname == 'localhost': - has_localhosts = True - self.hosts_cache['localhost'] = {'auth_methods': ['local'], - 'ansible_user': ansible_user} - result.append({'host': 'localhost', - 'auth': ['local']}) - continue - - output = b'' - try: - output = subprocess.check_output(['ssh', - '-o BatchMode=yes', - '-o ConnectTimeout=5', - '-o StrictHostKeyChecking=no', - '-o GSSAPIAuthentication=yes', - '-o PubkeyAuthentication=no', - '{0}@{1}'.format(ansible_user, target_hostname), - 'echo fpctl GSSAPIAuthentication ok'], - stderr=subprocess.STDOUT) - logging.debug('SSH GSSAPI check output:{}'.format(output.decode(sys.stdout.encoding))) - except subprocess.CalledProcessError as e: - logging.debug('SSH GSSAPI check error: {}'.format(e.output)) - - gssapi_auth_ok = 'fpctl GSSAPIAuthentication ok' in output.decode(sys.stdout.encoding) - - try: - output = subprocess.check_output(['ssh', - '-o BatchMode=yes', - '-o ConnectTimeout=5', - '-o StrictHostKeyChecking=no', - '-o GSSAPIAuthentication=no', - '-o PubkeyAuthentication=yes', - '{0}@{1}'.format(ansible_user, target_hostname), - 'echo fpctl PubkeyAuthentication ok'], - stderr=subprocess.STDOUT) - logging.debug('SSH Pubkey check output:{}'.format(output.decode(sys.stdout.encoding))) - except subprocess.CalledProcessError as e: - logging.debug('SSH Pubkey check error: {}'.format(e.output)) - - pubkey_auth_ok = 'fpctl PubkeyAuthentication ok' in output.decode(sys.stdout.encoding) - - self.hosts_cache[target_hostname] = {'auth_methods': [], - 'ansible_user': ansible_user} - if not pubkey_auth_ok and not gssapi_auth_ok: - hosts_that_cannot_ssh.append((target_hostname, ansible_user)) - - if pubkey_auth_ok or gssapi_auth_ok: - auth_ok = [] - if pubkey_auth_ok: - auth_ok.append('public key') - self.hosts_cache[target_hostname]['auth_methods'].append('public key') - if gssapi_auth_ok: - auth_ok.append('GSSAPI/Kerberos') - self.hosts_cache[target_hostname]['auth_methods'].append('GSSAPI/Kerberos') - result.append({'host': target_hostname, 'auth': auth_ok}) - - if has_localhosts: - print(C_QUEST + 'At least one of your target systems is localhost. SSH authentication ' - 'checks were skipped for localhost inventory entries. ' - 'Make sure that you have ansible_connection=local ' - 'in your inventory, and that passwordless sudo is enabled.') - - if hosts_that_cannot_ssh: - print(C_WARN + 'The following hosts do not appear to support passwordless ' - 'authentication (through either GSSAPI/Kerberos or public key):') - for host_user_tuple in hosts_that_cannot_ssh: - print(C_ITEM + '{0}@{1}'.format(host_user_tuple[1], host_user_tuple[0])) - if not self.force_deploy_ssh_keys: - self.force_deploy_ssh_keys = \ - query_yes_no('fpctl can try to enable passwordless public key ' - 'authentication (excluding Kerberos) on these ' - 'hosts by adding your SSH public key ' - 'to their authorized keys list. ' - 'Would you like to proceed?', default="yes") - - if self.force_deploy_ssh_keys: - self.__deploy_ssh_keys(hosts_that_cannot_ssh) - else: - print(C_RED + 'Since Ansible requires passwordless authentication on the target ' - 'hosts in order to work, fpctl cannot continue.\n' + C_RED + - 'Please see {} for instructions on how to ' - 'set up passwordless authentication for Ansible/fpctl.' - .format(ANSIBLE_SSH_DOCUMENTATION)) - self.__write_cache() - sys.exit(1) - - print(C_MSG + 'Hosts in inventory:') - for item in result: - print(C_ITEM + item['host'] + ' [authentication: ' + ', '.join(item['auth']) + ']') - - def __check_for_sudo_nopasswd(self, force=False): - for target_hostname in self.inventory_hosts: - ansible_user = os.environ.get('USER') - for line in self.inventory_file_lines: - if line.startswith(target_hostname) and 'ansible_user='in line: - splitline = line.split(' ') - for word in splitline: - if word.startswith('ansible_user='): - ansible_user = word.strip()[13:] - break # we found an ansible_user override, so we break and go on - - become_with_ksu = False - for line in self.inventory_file_lines: - if line.startswith(target_hostname) and 'ansible_become_method=ksu' in line: - become_with_ksu = True - break # if this host is set up with Kerberos+ksu, we skip to the next - if become_with_ksu: - continue - - if not force and \ - target_hostname in self.hosts_cache and \ - 'sudo_nopasswd' in self.hosts_cache[target_hostname] and \ - self.hosts_cache[target_hostname]['sudo_nopasswd'] and \ - 'ansible_user' in self.hosts_cache[target_hostname] and \ - self.hosts_cache[target_hostname]['ansible_user'] == ansible_user: - continue - - output = b'' - if target_hostname == 'localhost': - try: - output = subprocess.check_output(['/bin/sudo -kn echo "fpctl sudo ok"'], - shell=True, - stderr=subprocess.STDOUT) - logging.debug('local sudo check output:{}'.format(output.decode(sys.stdout.encoding))) - except subprocess.CalledProcessError as e: - logging.debug('local sudo check error: {}'.format(e.output)) - else: - try: - output = subprocess.check_output(['ssh', - '-o BatchMode=yes', - '-o ConnectTimeout=5', - '-o StrictHostKeyChecking=no', - '{0}@{1}'.format(ansible_user, target_hostname), - '/bin/sudo -kn echo "fpctl sudo ok"'], - stderr=subprocess.STDOUT) - logging.debug('SSH sudo check output:{}'.format(output.decode(sys.stdout.encoding))) - except subprocess.CalledProcessError as e: - logging.debug('SSH sudo check error: {}'.format(e.output)) - - sudo_ok = 'fpctl sudo ok' in output.decode(sys.stdout.encoding) - self.hosts_cache[target_hostname]['sudo_nopasswd'] = sudo_ok - - if not sudo_ok: - if query_yes_no('Passwordless sudo not set on host {0}. fpctl requires ' - 'sudo NOPASSWD configuration in order to work. To ' - 'enable this, you should add a file named "zzz-fpctl" to ' - 'the /etc/sudoers.d directory on host {0}, with the ' - 'content "{1} ALL=(ALL) NOPASSWD: ALL".\n' - 'You may quit fpctl and do it yourself, or fpctl can do ' - 'this for you now. Do you wish to proceed with enabling ' - 'passwordless sudo?'.format(target_hostname, ansible_user), - default="yes"): - sudoers_extra_path = '/etc/sudoers.d/zzz-fpctl' - - file_cmd = '/bin/sudo -Sk su -c "EDITOR=tee visudo -f {}"' \ - .format(sudoers_extra_path) - password = getpass.getpass(prompt='[sudo] password for {0}@{1}: ' - .format(ansible_user, target_hostname)) - sudoers_line = '{} ALL=(ALL) NOPASSWD: ALL\n'.format(ansible_user) - - if target_hostname == 'localhost': - p = subprocess.Popen(file_cmd, - shell=True, - stdin=subprocess.PIPE, - stderr=subprocess.PIPE, - stdout=subprocess.DEVNULL, - universal_newlines=True) - else: - p = subprocess.Popen(['ssh', - '-o BatchMode=yes', - '-o ConnectTimeout=5', - '-o StrictHostKeyChecking=no', - '{0}@{1}'.format(ansible_user, target_hostname), - file_cmd], - stdin=subprocess.PIPE, - stderr=subprocess.PIPE, - stdout=subprocess.DEVNULL, - universal_newlines=True) - - p.communicate('{0}\n{1}'.format(password, sudoers_line)) - if p.returncode: - print(C_ERR + 'Could not set up passwordless sudo on host {}. fpctl will now quit.' - .format(target_hostname)) - self.__write_cache() - sys.exit(p.returncode) - else: - self.hosts_cache[target_hostname]['sudo_nopasswd'] = True - print(C_MSG + 'Passwordless sudo OK on host {}.'.format(target_hostname)) - - else: - print(C_ERR + 'Passwordless sudo not allowed on host {}. fpctl will now quit.' - .format(target_hostname)) - self.__write_cache() - sys.exit(0) - - -def __get_next_run_number(): - run_number_path = os.path.join(FPCTL_CONFIG_DIR, "run_counter") - last_run_number = 0 - - if os.path.isfile(run_number_path): - run_number_line = "" - with open(run_number_path, 'r') as run_counter: - run_number_line = run_counter.readline() - last_run_number = int(run_number_line) - - run_number = last_run_number + 1 - - with open(run_number_path, 'w') as run_counter: - run_counter.writelines([str(run_number)]) - - return run_number - - -def check_for_correct_task(args): - if args.task: - if args.task not in TASK_NAMES: - print(C_ERR + 'Unknown task "{}".'.format(args.task)) - print(C_RED + 'Available tasks:') - for task_name in TASK_NAMES: - print(C_ITEM + task_name) - sys.exit(1) - - -def print_summary(inventory_path): - all_target_groups = TARGET_GROUPS + ['qc-repository', 'infologger-server'] - all_task_names = TASK_NAMES + [Style.RESET_ALL + Style.DIM + Fore.WHITE + '(none)' + Style.RESET_ALL, - Style.RESET_ALL + Style.DIM + Fore.WHITE + '(none)' + Style.RESET_ALL] - systemd_units = ['flpprototype-readout', - 'flpprotocype-qctask', - 'flpprototype-qcchecker', - Style.RESET_ALL + Style.DIM + Fore.WHITE + '(none)' + Style.RESET_ALL, - 'o2-infologger-server'] - target_hosts = [] - for group in all_target_groups: - output = subprocess.check_output(['ansible', - group, - '-i{}'.format(inventory_path), - '--list-hosts']) - if b'hosts (0)' in output: - target_hosts.append([]) - continue - - inventory_hosts = output.decode(sys.stdout.encoding).splitlines() - inventory_hosts = inventory_hosts[1:] # we throw away the first line which is only a summary - inventory_hosts = [line.strip() for line in inventory_hosts] - target_hosts.append(inventory_hosts) - - headers = list('\n'.join(Style.BRIGHT + Fore.BLUE + line + Style.RESET_ALL for line in item.splitlines()) for item in - ['Inventory groups', - 'Target hosts', - 'Systemd units\n(on target hosts)', - 'Tasks\n(accessible through fpctl)']) - - rows = list(zip(('[' + item + ']' for item in all_target_groups), - ('\n'.join(item) for item in target_hosts), - systemd_units, - (Style.BRIGHT + Fore.BLUE + item + Style.RESET_ALL for item in all_task_names))) - - table = SingleTable([headers] + - rows) - table.inner_row_border = True - table.CHAR_H_INNER_HORIZONTAL = b'\xcd'.decode('ibm437') - table.CHAR_OUTER_TOP_HORIZONTAL = b'\xcd'.decode('ibm437') - table.CHAR_OUTER_TOP_LEFT = b'\xd5'.decode('ibm437') - table.CHAR_OUTER_TOP_RIGHT = b'\xb8'.decode('ibm437') - table.CHAR_OUTER_TOP_INTERSECT = b'\xd1'.decode('ibm437') - table.CHAR_H_OUTER_LEFT_INTERSECT = b'\xc6'.decode('ibm437') - table.CHAR_H_OUTER_RIGHT_INTERSECT = b'\xb5'.decode('ibm437') - table.CHAR_H_INNER_INTERSECT = b'\xd8'.decode('ibm437') - print(table.table) - print(C_MSG + 'Configuration files were deployed in /etc/flpprototype.d on the target systems.') - print(C_MSG + 'FLP prototype software is installed in /opt/alisw. If you wish to use ' + - 'it manually, you must run "module load flpproto" after you SSH into a target system.') - print(C_MSG + 'It is now possible to control the tasks listed in the last column through fpctl.') - print(C_MSG + 'Also, if you have a local instance of InfoBrowser, you may use it with this ' + - 'configuration file: {} by copying the file to your /etc directory.'.format(os.path.join(FPCTL_CONFIG_DIR, 'infoLogger.cfg'))) - - -def query_yes_no(question, default="yes"): - """Ask a yes/no question via raw_input() and return their answer. - - "question" is a string that is presented to the user. - "default" is the presumed answer if the user just hits . - It must be "yes" (the default), "no" or None (meaning - an answer is required of the user). - - The "answer" return value is True for "yes" or False for "no". - """ - valid = {"yes": True, "y": True, "ye": True, - "no": False, "n": False} - if default is None: - prompt = " [y/n] " - elif default == "yes": - prompt = " [Y/n] " - elif default == "no": - prompt = " [y/N] " - else: - raise ValueError("invalid default answer: '%s'" % default) - - while True: - sys.stdout.write(C_QUEST + - question + prompt + '\n' + - C_QUEST + '------------------------------------\n' + - C_QUEST) - choice = input().lower() - if default is not None and choice == '': - return valid[default] - elif choice in valid: - return valid[choice] - else: - sys.stdout.write(C_QUEST + - "Please respond with 'yes' or 'no' " - "(or 'y' or 'n').\n" + - C_QUEST) - - -def get_inventory_path(inventory_option): - """Get the path of the inventory file. May interact with user.""" - inventory_path = DEFAULT_INVENTORY_PATH - - if inventory_option: - inventory_path = os.path.abspath(inventory_option) - if not os.path.isfile: - raise FileNotFoundError(errno.ENOENT, - os.strerror(errno.ENOENT), - inventory_path) - else: - return inventory_path - else: - if not os.path.isfile(inventory_path): - if query_yes_no('Ansible inventory file not found at {}. fpctl can ' - 'autogenerate a default one for you, with target localhost. ' - 'This means that all FLP prototype software will be ' - 'deployed on your current system. ' - 'Would you like to proceed?' - .format(inventory_path), default="yes"): - with open(inventory_path, 'w') as inventory_file: - loc = 'localhost ansible_connection=local' - inv = '' - for group in [INVENTORY_READOUT_GROUP, - INVENTORY_QCTASK_GROUP, - INVENTORY_QCCHECKER_GROUP, - INVENTORY_QCREPOSITORY_GROUP, - INVENTORY_INFOLOGGERSERVER_GROUP]: - inv += '[{0}]\n{1}\n'.format(group, loc) - print("{}".format(inv), file=inventory_file) - else: - raise FileNotFoundError(errno.ENOENT, - os.strerror(errno.ENOENT), - inventory_path) - return inventory_path - - -def deploy(args): - """Handler for deploy command""" - inventory_path = get_inventory_path(args.inventory) - - inv = Inventory(inventory_path) - inv.load() - inv.check_hosts(force=True) - - ansible_cwd = os.path.join(FPCTL_DATA_DIR, 'system-configuration/ansible') - - ansible_systemd_path = os.path.join(FPCTL_DATA_DIR, 'Control/fpctl/systemd/system') - ansible_systemd_var = 'flpprototype_systemd={}'.format(ansible_systemd_path) - - ansible_extra_params = [] - if (args.ansible_extra_params): - ansible_extra_params += args.ansible_extra_params.split(' ') - - ansible_extra_vars = [ansible_systemd_var] - if (args.ansible_extra_vars): - ansible_extra_vars += args.ansible_extra_vars.split(' ') - - ansible_cmd = ['ansible-playbook', - os.path.join(ansible_cwd, 'site.yml'), - '-i{}'.format(inventory_path), - '-s', - '-e"{}"'.format(' '.join(ansible_extra_vars))] - if args.verbose: - ansible_cmd += ['-vvv'] - if ansible_extra_params: - ansible_cmd += ansible_extra_params - - ansible_env = os.environ.copy() - ansible_env['ANSIBLE_CONFIG'] = os.path.join(FPCTL_CONFIG_DIR, 'ansible.cfg') - - ansible_proc = subprocess.Popen(' '.join(ansible_cmd), - shell=True, - cwd=ansible_cwd, - env=ansible_env) - ansible_proc.communicate() - print(C_MSG + 'Deployment summary:') - print_summary(inventory_path) - print(C_MSG + 'All done.') - - -def configure(args): - """Handler for configure command""" - - inventory_path = get_inventory_path(args.inventory) - - inv = Inventory(inventory_path) - inv.load() - inv.check_hosts() - - ansible_cwd = os.path.join(FPCTL_DATA_DIR, 'system-configuration/ansible') - - ansible_systemd_path = os.path.join(FPCTL_DATA_DIR, 'Control/fpctl/systemd/system') - ansible_systemd_var = 'flpprototype_systemd={}'.format(ansible_systemd_path) - - ansible_extra_params = [] - if (args.ansible_extra_params): - ansible_extra_params += args.ansible_extra_params.split(' ') - - ansible_extra_vars = [ansible_systemd_var] - if (args.ansible_extra_vars): - ansible_extra_vars += args.ansible_extra_vars.split(' ') - - ansible_cmd = ['ansible-playbook', - os.path.join(ansible_cwd, 'site.yml'), - '-i{}'.format(inventory_path), - '-s', - '-tconfiguration' - '-e"{}"'.format(' '.join(ansible_extra_vars))] - if args.verbose: - ansible_cmd += ['-vvv'] - if ansible_extra_params: - ansible_cmd += ansible_extra_params - - ansible_env = os.environ.copy() - ansible_env['ANSIBLE_CONFIG'] = os.path.join(FPCTL_CONFIG_DIR, 'ansible.cfg') - - ansible_proc = subprocess.Popen(' '.join(ansible_cmd), - shell=True, - cwd=ansible_cwd, - env=ansible_env) - ansible_proc.communicate() - print(C_MSG + 'Configuration summary:') - print_summary(inventory_path) - print(C_MSG + 'All done.') - - -def run(args): - """Handler for run command""" - - inventory_path = get_inventory_path(args.inventory) - - inv = Inventory(inventory_path) - inv.load() - inv.check_hosts() - - host = args.host - custom_command = args.command - - ansible_extra_params = [] - if (args.ansible_extra_params): - ansible_extra_params += args.ansible_extra_params.split(' ') - - ansible_extra_vars = [] - if (args.ansible_extra_vars): - ansible_extra_vars += args.ansible_extra_vars.split(' ') - - ansible_cmd = ['ansible', - host, - '-i"{}"'.format(inventory_path)] - if args.verbose: - ansible_cmd += ['-vvv'] - if ansible_extra_params: - ansible_cmd += ansible_extra_params - if ansible_extra_vars: - ansible_cmd += ['-e"{}"'.format(' '.join(ansible_extra_vars))] - - ansible_cmd += ['-a"{}"'.format(custom_command)] - ansible_env = os.environ.copy() - ansible_env['ANSIBLE_CONFIG'] = os.path.join(FPCTL_CONFIG_DIR, 'ansible.cfg') - - ansible_proc = subprocess.Popen(' '.join(ansible_cmd), - shell=True, - env=ansible_env) - ansible_proc.communicate() - print(C_MSG + 'All done.') - - -def start(args): - """Handler for start command""" - - inventory_path = get_inventory_path(args.inventory) - - check_for_correct_task(args) - inv = Inventory(inventory_path) - inv.load() - inv.check_hosts() - - ansible_cwd = os.path.join(FPCTL_DATA_DIR, 'system-configuration/ansible') - - ansible_extra_params = [] - if (args.ansible_extra_params): - ansible_extra_params += args.ansible_extra_params.split(' ') - - ansible_extra_vars = [] - if (args.ansible_extra_vars): - ansible_extra_vars += args.ansible_extra_vars.split(' ') - - ansible_extra_vars += "fpctl_run_number={}".format(__get_next_run_number()) - - ansible_cmd = ['ansible-playbook', - os.path.join(ansible_cwd, 'control.yml'), - '-i{}'.format(inventory_path), - '-s', - '-t{}control-start' - .format('{}-'.format(args.task) if args.task else '')] - if args.verbose: - ansible_cmd += ['-vvv'] - if ansible_extra_params: - ansible_cmd += ansible_extra_params - if ansible_extra_vars: - ansible_cmd += ['-e"{}"'.format(' '.join(ansible_extra_vars))] - - ansible_env = os.environ.copy() - ansible_env['ANSIBLE_CONFIG'] = os.path.join(FPCTL_CONFIG_DIR, 'ansible.cfg') - - ansible_proc = subprocess.Popen(' '.join(ansible_cmd), - shell=True, - cwd=ansible_cwd, - env=ansible_env) - ansible_proc.communicate() - print(C_MSG + 'All done.') - - -def status(args): - """Handler for status command""" - inventory_path = get_inventory_path(args.inventory) - - check_for_correct_task(args) - inv = Inventory(inventory_path) - inv.load() - inv.check_hosts() - - ansible_cwd = os.path.join(FPCTL_DATA_DIR, 'system-configuration/ansible') - - ansible_extra_params = [] - if (args.ansible_extra_params): - ansible_extra_params += args.ansible_extra_params.split(' ') - - ansible_extra_vars = [] - if (args.ansible_extra_vars): - ansible_extra_vars += args.ansible_extra_vars.split(' ') - - print(C_MSG + 'Checking status...') - - ansible_cmd = ['ansible-playbook', - os.path.join(ansible_cwd, 'control.yml'), - '-i{}'.format(inventory_path), - '-s', - '-t{}control-status' - .format('{}-'.format(args.task) if args.task else '')] - if args.verbose: - ansible_cmd += ['-vvv'] - if ansible_extra_params: - ansible_cmd += ansible_extra_params - if ansible_extra_vars: - ansible_cmd += ['-e"{}"'.format(' '.join(ansible_extra_vars))] - - ansible_env = os.environ.copy() - ansible_env['ANSIBLE_CONFIG'] = os.path.join(FPCTL_CONFIG_DIR, 'ansible.cfg') - - rp = Reprinter() - - previous_now = datetime.datetime.now() - loop = True - try: - while loop: - if not args.follow: - loop = False - - ansible_proc = subprocess.Popen(' '.join(ansible_cmd), - shell=True, - cwd=ansible_cwd, - env=ansible_env, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - - output_lines = [] - if args.verbose: - while True: - nextline = ansible_proc.stdout.readline() - u_nextline = nextline.decode(sys.stdout.encoding) - if 'PLAY RECAP' in u_nextline.strip(): - break - sys.stdout.write(u_nextline) - output_lines.append(u_nextline.rstrip()) - sys.stdout.flush() - - out, err = ansible_proc.communicate() - - if not args.verbose: - output_lines = out.decode(sys.stdout.encoding).splitlines() - - # The output from the a control playbook contains a specially formatted debug - # module instance. We need to extract it and parse it as JSON. - in_json = False - json_entries = [] - for line in output_lines: - if 'TASK' in line and 'control-status-output-json' in line: - in_json = True - continue - if in_json: - if line.startswith('task path') or line.startswith('META:'): - continue - if line.startswith('ok: ['): - json_entries.append('{\n') - elif not line.strip(): - in_json = False - else: - json_entries[-1] += (line + '\n') - else: - continue - - # print(C_MSG + 'Raw output:\n' + '\n'.join(output_lines)) - json_objects = [] - for entry in json_entries: - # print(C_ITEM + 'ITEM: ' + entry) - obj = json.loads(entry) - # print(C_ITEM + 'OBJECT:' + str(obj)) - json_objects.append(obj['msg']) - - # By service - tables = dict() - rows = [] - available_task_names = TASK_NAMES - available_target_groups = TARGET_GROUPS - if args.task: - # this is ok because check_for_correct_task runs early on - available_task_names = [args.task] - available_target_groups = [TARGET_GROUPS[TASK_NAMES.index(args.task)]] - - for i in range(len(available_task_names)): - servicename = available_task_names[i] - target_group = available_target_groups[i] - if servicename not in tables: - tables[servicename] = list() - - for obj in json_objects: - if obj['service'] == servicename: - units = dict() - for line in obj['systemctl_status_output']: - unitname = line.split(':')[0] - unitstatus = line.split(':')[1] - unitname = re.sub('\.service$', '', unitname) - units[unitname] = unitstatus - - for line in obj['systemctl_list_unit_files_output']: - unitname = re.sub('\.service$', '', line) - if '@' in unitname: - continue - if unitname not in units: - units[unitname] = 'inactive' - - units = OrderedDict(sorted(units.items())) - - unitnames = [] - unitstatuses = [] - for i, (unitname, unitstatus) in enumerate(units.items()): - c_bullet = BULLET - if unitstatus == 'active': - c_bullet = Style.BRIGHT + Fore.GREEN + BULLET + Style.RESET_ALL - elif unitstatus == 'reloading' or unitstatus == 'activating' or unitstatus == 'deactivating': - c_bullet = Style.BRIGHT + Fore.YELLOW + BULLET + Style.RESET_ALL - elif unitstatus == 'inactive': - c_bullet = Style.BRIGHT + Fore.WHITE + BULLET + Style.RESET_ALL - elif unitstatus == 'failed' or unitstatus == 'error': - c_bullet = Style.BRIGHT + Fore.RED + BULLET + Style.RESET_ALL - - unitnames.append(' ' + unitname) - unitstatuses.append(c_bullet + unitstatus) - - tables[servicename].append([' ' + obj['host'], - '\n'.join(unitnames), - '\n'.join(unitstatuses)]) - - tables[servicename] = sorted(tables[servicename], key=itemgetter(0)) - for row in tables[servicename]: - if not row[1]: - row[1] = Style.DIM + Fore.WHITE + ' (no units found)' + Style.RESET_ALL - if not row[2]: - row[2] = Style.DIM + Fore.WHITE + BULLET + '(none)' + Style.RESET_ALL - - headers = [Style.BRIGHT + Fore.BLUE + 'Inventory group' + Style.RESET_ALL + '\n Target hosts', - Style.BRIGHT + Fore.BLUE + 'Task' + Style.RESET_ALL + '\n Systemd units', - ' \nStatus'] - - rows += [[Style.BRIGHT + Fore.BLUE + '[' + target_group + ']' + Style.RESET_ALL, - Style.BRIGHT + Fore.BLUE + servicename + Style.RESET_ALL]] - rows += tables[servicename] - - table = SingleTable([headers] + - rows) - table.inner_row_border = True - table.inner_column_border = False - table.CHAR_H_INNER_HORIZONTAL = b'\xcd'.decode('ibm437') - table.CHAR_OUTER_TOP_HORIZONTAL = b'\xcd'.decode('ibm437') - table.CHAR_OUTER_TOP_LEFT = b'\xd5'.decode('ibm437') - table.CHAR_OUTER_TOP_RIGHT = b'\xb8'.decode('ibm437') - table.CHAR_OUTER_TOP_INTERSECT = b'\xd1'.decode('ibm437') - table.CHAR_H_OUTER_LEFT_INTERSECT = b'\xc6'.decode('ibm437') - table.CHAR_H_OUTER_RIGHT_INTERSECT = b'\xb5'.decode('ibm437') - table.CHAR_H_INNER_INTERSECT = b'\xd8'.decode('ibm437') - - if not args.follow: - print(table.table) - return - - now = datetime.datetime.now() - MIN_DELAY_SECONDS = 1 - if now - previous_now < datetime.timedelta(seconds=MIN_DELAY_SECONDS): - time.sleep((datetime.timedelta(seconds=MIN_DELAY_SECONDS) - (now - previous_now)).total_seconds()) - now = datetime.datetime.now() - table.title = now.strftime('%y-%m-%d %H:%M:%S') - to_print = (table.table + '\n' + - C_YELL + 'Status refreshed in {0:.2f} seconds. [Ctrl+C] to quit.\n' - .format((now - previous_now).total_seconds())) - rp.reprint(to_print) - previous_now = now - - except KeyboardInterrupt as e: - print('\n' + C_MSG + 'User interrupt.') - sys.exit(0) - - -def stop(args): - """Handler for stop command""" - inventory_path = get_inventory_path(args.inventory) - - check_for_correct_task(args) - inv = Inventory(inventory_path) - inv.load() - inv.check_hosts() - - ansible_cwd = os.path.join(FPCTL_DATA_DIR, 'system-configuration/ansible') - - ansible_extra_params = [] - if (args.ansible_extra_params): - ansible_extra_params += args.ansible_extra_params.split(' ') - - ansible_extra_vars = [] - if (args.ansible_extra_vars): - ansible_extra_vars += args.ansible_extra_vars.split(' ') - - ansible_cmd = ['ansible-playbook', - os.path.join(ansible_cwd, 'control.yml'), - '-i{}'.format(inventory_path), - '-s', - '-t{}control-stop' - .format('{}-'.format(args.task) if args.task else '')] - if args.verbose: - ansible_cmd += ['-vvv'] - if ansible_extra_params: - ansible_cmd += ansible_extra_params - if ansible_extra_vars: - ansible_cmd += ['-e"{}"'.format(' '.join(ansible_extra_vars))] - - ansible_env = os.environ.copy() - ansible_env['ANSIBLE_CONFIG'] = os.path.join(FPCTL_CONFIG_DIR, 'ansible.cfg') - - ansible_proc = subprocess.Popen(' '.join(ansible_cmd), - shell=True, - cwd=ansible_cwd, - env=ansible_env) - ansible_proc.communicate() - print(C_MSG + 'All done.') - - -def main(argv): - """Entry point, called by fpctl script.""" - args = argv[1:] - inventory_help = 'path to an Ansible infentory file (default: ~/.config/fpctl/inventory)' - verbose_help = 'print more output for debugging purposes' - ansible_extra_params_help = 'additional command line parameters to be passed to Ansible, enclosed in quotes' - ansible_extra_vars_help = 'additional variables for Ansible as key=value or JSON, enclosed in quotes' - - parser = argparse.ArgumentParser(description=C_MSG + 'FLP prototype control utility', - prog='fpctl', - epilog='run "fpctl OPERATION --help" for information on a specific fpctl operation', - formatter_class=argparse.RawDescriptionHelpFormatter) - subparsers = parser.add_subparsers(dest='subparser_name') - - sp_deploy = subparsers.add_parser('deploy', - aliases=['de'], - help='deploy FLP prototype software and configuration') - sp_deploy.add_argument('--inventory', '-i', metavar='INVENTORY', help=inventory_help) - sp_deploy.add_argument('--verbose', '-v', help=verbose_help, action='store_true') - sp_deploy.add_argument('--ansible-extra-params', '-p', metavar='ANSIBLE_PARAMS', help=ansible_extra_params_help) - sp_deploy.add_argument('--ansible-extra-vars', '-e', metavar='ANSIBLE_VARS', help=ansible_extra_vars_help) - sp_deploy.set_defaults(func=deploy) - - sp_configure = subparsers.add_parser('configure', - aliases=['co'], - help='deploy FLP prototype configuration') - sp_configure.add_argument('--inventory', '-i', metavar='INVENTORY', help=inventory_help) - sp_configure.add_argument('--verbose', '-v', help=verbose_help, action='store_true') - sp_configure.add_argument('--ansible-extra-params', '-p', metavar='ANSIBLE_PARAMS', help=ansible_extra_params_help) - sp_configure.add_argument('--ansible-extra-vars', '-e', metavar='ANSIBLE_VARS', help=ansible_extra_vars_help) - sp_configure.set_defaults(func=configure) - - sp_run = subparsers.add_parser('run', - help='run a custom command on one or all nodes') - sp_run.add_argument('--inventory', '-i', metavar='INVENTORY', help=inventory_help) - sp_run.add_argument('--verbose', '-v', help=verbose_help, action='store_true') - sp_run.add_argument('--ansible-extra-params', '-p', metavar='ANSIBLE_PARAMS', help=ansible_extra_params_help) - sp_run.add_argument('--ansible-extra-vars', '-e', metavar='ANSIBLE_VARS', help=ansible_extra_vars_help) - sp_run.add_argument('host', metavar='HOST', - help='a hostname, an Ansible inventory group, or "all"') - sp_run.add_argument('command', metavar='COMMAND', - help='the command to run on the target node (use quotes ' - 'if it contains whitespace)') - sp_run.set_defaults(func=run) - - sp_start = subparsers.add_parser('start', - help='start some or all FLP prototype processes') - sp_start.add_argument('--inventory', '-i', metavar='INVENTORY', help=inventory_help) - sp_start.add_argument('--verbose', '-v', help=verbose_help, action='store_true') - sp_start.add_argument('--ansible-extra-params', '-p', metavar='ANSIBLE_PARAMS', help=ansible_extra_params_help) - sp_start.add_argument('--ansible-extra-vars', '-e', metavar='ANSIBLE_VARS', help=ansible_extra_vars_help) - sp_start.add_argument('task', metavar='TASK', nargs='?', - help='the task to start on the nodes, as configured in the ' - 'inventory file') - sp_start.set_defaults(func=start) - - sp_status = subparsers.add_parser('status', - help='view status of some or all FLP prototype processes') - sp_status.add_argument('--inventory', '-i', metavar='INVENTORY', help=inventory_help) - sp_status.add_argument('--verbose', '-v', help=verbose_help, action='store_true') - sp_status.add_argument('--follow', '-f', help='keep querying the status', action='store_true') - sp_status.add_argument('--ansible-extra-params', '-p', metavar='ANSIBLE_PARAMS', help=ansible_extra_params_help) - sp_status.add_argument('--ansible-extra-vars', '-e', metavar='ANSIBLE_VARS', help=ansible_extra_vars_help) - sp_status.add_argument('task', metavar='TASK', nargs='?', - help='the task on the nodes for which to query the status, as ' - 'configured in the inventory file') - sp_status.set_defaults(func=status) - - sp_stop = subparsers.add_parser('stop', - help='stop some or all FLP prototype processes') - sp_stop.add_argument('--inventory', '-i', metavar='INVENTORY', help=inventory_help) - sp_stop.add_argument('--verbose', '-v', help=verbose_help, action='store_true') - sp_stop.add_argument('--ansible-extra-params', '-p', metavar='ANSIBLE_PARAMS', help=ansible_extra_params_help) - sp_stop.add_argument('--ansible-extra-vars', '-e', metavar='ANSIBLE_VARS', help=ansible_extra_vars_help) - sp_stop.add_argument('task', metavar='TASK', nargs='?', - help='the task to stop on the nodes, as configured in the ' - 'inventory file') - sp_stop.set_defaults(func=stop) - - # Update and setup are fake entries with the only purpose of generating documentation. - # They are handled by the fpctl shell script - subparsers.add_parser('update', - aliases=['up'], - help='update fpctl deployment information') - subparsers.add_parser('setup', - help='install and configure fpctl') - - parsed_args = parser.parse_args(args) - logging.debug('argparse output: {}'.format(vars(parsed_args))) - - if not parsed_args.subparser_name: - print(C_ERR + 'No operation specified.') - parser.print_help() - sys.exit(1) - - parsed_args.func(parsed_args) - - -if __name__ == '__main__': - main(sys.argv) diff --git a/fpctl/systemd/system/README.md b/fpctl/systemd/system/README.md deleted file mode 100644 index 51d4e92ec..000000000 --- a/fpctl/systemd/system/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Systemd templates for FLP prototype - -These are Jinja2 templates, to be deployed through Ansible which then outputs proper Systemd units. diff --git a/fpctl/systemd/system/flpprototype-qcchecker.service.j2 b/fpctl/systemd/system/flpprototype-qcchecker.service.j2 deleted file mode 100644 index ba21a5bd5..000000000 --- a/fpctl/systemd/system/flpprototype-qcchecker.service.j2 +++ /dev/null @@ -1,11 +0,0 @@ -[Unit] -Description=O2 FlpPrototype QC checker process -After=network.target -AssertPathExistsGlob={{ flpprototype_qc_confdir }}/{{ flpprototype_qc_default_config }} - -[Service] -ExecStart=/bin/sh -c "source /etc/profile.d/modules.sh && \ - MODULEPATH={{ o2_install_path }}/modulefiles module load {{ flpprototype_qc_packagebasename }}/{{ flpprototype_qc_packageversion }} && \ - {{ o2_install_path }}/{{ flpprototype_qc_packagebasename }}/{{flpprototype_qc_packageversion}}/bin/qcCheckerLauncher \ - -n checker_0 -c json://{{ flpprototype_qc_confdir }}/{{ flpprototype_qc_default_config }} | {{ infologger_install_path }}/bin/log -x" -Restart=no diff --git a/fpctl/systemd/system/flpprototype-qcchecker@.service.j2 b/fpctl/systemd/system/flpprototype-qcchecker@.service.j2 deleted file mode 100644 index 650ce7b55..000000000 --- a/fpctl/systemd/system/flpprototype-qcchecker@.service.j2 +++ /dev/null @@ -1,13 +0,0 @@ -[Unit] -Description=O2 FlpPrototype QC checker process -After=network.target - -# Syntax: sudo systemctl start flpprototype-qcchecker@task_name@config_file_name -[Service] -ExecStart=/bin/sh -c "source /etc/profile.d/modules.sh && \ - MODULEPATH={{ o2_install_path }}/modulefiles module load {{ flpprototype_qc_packagebasename }}/{{ flpprototype_qc_packageversion }} && \ - QCCHECKERNAME=`/bin/echo '%i' | /bin/cut -f1 -d@` && \ - QCCONFIGFILENAME=`/bin/echo '%i' | /bin/cut -f2 -d@` && \ - {{ o2_install_path }}/{{ flpprototype_qc_packagebasename }}/{{flpprototype_qc_packageversion}}/bin/qcCheckerLauncher \ - -n $${QCCHECKERNAME} -c json://{{ flpprototype_qc_confdir }}/$${QCCONFIGFILENAME}.ini | {{ infologger_install_path }}/bin/log -x" -Restart=no diff --git a/fpctl/systemd/system/flpprototype-qctask.service.j2 b/fpctl/systemd/system/flpprototype-qctask.service.j2 deleted file mode 100644 index 561089778..000000000 --- a/fpctl/systemd/system/flpprototype-qctask.service.j2 +++ /dev/null @@ -1,13 +0,0 @@ -[Unit] -Description=O2 FlpPrototype QC task process -After=network.target -AssertPathExistsGlob={{ flpprototype_qc_confdir }}/{{ flpprototype_qc_default_config }} - -[Service] -ExecStart=/bin/sh -c "source /etc/profile.d/modules.sh && \ - MODULEPATH={{ o2_install_path }}/modulefiles module load {{ flpprototype_qc_packagebasename }}/{{ flpprototype_qc_packageversion }} && \ - {{ o2_install_path }}/{{ flpprototype_qc_packagebasename }}/{{flpprototype_qc_packageversion}}/bin/qcTaskLauncher \ - -n myTask_1 -c json://{{ flpprototype_qc_confdir }}/{{ flpprototype_qc_default_config }} \ - --id myTask_1 --mq-config {{ flpprototype_qc_confdir }}/{{ flpprototype_qc_fairmq_config }} \ - --control static | {{ infologger_install_path }}/bin/log -x" -Restart=no diff --git a/fpctl/systemd/system/flpprototype-qctask@.service.j2 b/fpctl/systemd/system/flpprototype-qctask@.service.j2 deleted file mode 100644 index d3c5c6af2..000000000 --- a/fpctl/systemd/system/flpprototype-qctask@.service.j2 +++ /dev/null @@ -1,15 +0,0 @@ -[Unit] -Description=O2 FlpPrototype QC task process -After=network.target - -# Syntax: sudo systemctl start flpprototype-qctask@task_name@config_file_name -[Service] -ExecStart=/bin/sh -c "source /etc/profile.d/modules.sh && \ - MODULEPATH={{ o2_install_path }}/modulefiles module load {{ flpprototype_qc_packagebasename }}/{{ flpprototype_qc_packageversion }} && \ - QCTASKNAME=`/bin/echo '%i' | /bin/cut -f1 -d@` && \ - QCCONFIGFILENAME=`/bin/echo '%i' | /bin/cut -f2 -d@` && \ - {{ o2_install_path }}/{{ flpprototype_qc_packagebasename }}/{{flpprototype_qc_packageversion}}/bin/qcTaskLauncher \ - -n $${QCTASKNAME} -c json://{{ flpprototype_qc_confdir }}/$${QCCONFIGFILENAME}.ini \ - --id $${QCTASKNAME} --mq-config {{ flpprototype_qc_confdir }}/{{ flpprototype_qc_fairmq_config }} \ - --control static | {{ infologger_install_path }}/bin/log -x" -Restart=no diff --git a/fpctl/systemd/system/flpprototype-readout.service.j2 b/fpctl/systemd/system/flpprototype-readout.service.j2 deleted file mode 100644 index ae51ade4a..000000000 --- a/fpctl/systemd/system/flpprototype-readout.service.j2 +++ /dev/null @@ -1,10 +0,0 @@ -[Unit] -Description=O2 FlpPrototype readout process -After=network.target -AssertPathExistsGlob={{ flpprototype_readout_confdir }}/{{ flpprototype_readout_default_config }} - -[Service] -ExecStart=/bin/sh -c "source /etc/profile.d/modules.sh && \ - MODULEPATH={{ o2_install_path }}/modulefiles module load {{ flpprototype_readout_packagebasename }}/{{ flpprototype_readout_packageversion }} && \ - {{ o2_install_path }}/{{ flpprototype_readout_packagebasename }}/{{flpprototype_readout_packageversion}}/bin/o2-readout-exe file:{{ flpprototype_readout_confdir }}/{{ flpprototype_readout_default_config }}" -Restart=no diff --git a/fpctl/systemd/system/flpprototype-readout@.service.j2 b/fpctl/systemd/system/flpprototype-readout@.service.j2 deleted file mode 100644 index a5594dae3..000000000 --- a/fpctl/systemd/system/flpprototype-readout@.service.j2 +++ /dev/null @@ -1,10 +0,0 @@ -[Unit] -Description=O2 FlpPrototype readout process -After=network.target -AssertPathExistsGlob={{ flpprototype_readout_confdir }}/%i.cfg - -[Service] -ExecStart=/bin/sh -c "source /etc/profile.d/modules.sh && \ - MODULEPATH={{ o2_install_path }}/modulefiles module load {{ flpprototype_readout_packagebasename }}/{{ flpprototype_readout_packageversion }} && \ - {{ o2_install_path }}/{{ flpprototype_readout_packagebasename }}/{{flpprototype_readout_packageversion}}/bin/readout.exe file:{{ flpprototype_readout_confdir }}/%i.cfg" -Restart=no diff --git a/fpctl/systemd/system/hugetlbfs.service.j2 b/fpctl/systemd/system/hugetlbfs.service.j2 deleted file mode 100644 index 52ea9667c..000000000 --- a/fpctl/systemd/system/hugetlbfs.service.j2 +++ /dev/null @@ -1,9 +0,0 @@ -[Unit] -Description=Set up hugetlbfs for readout - -[Service] -Type=oneshot -ExecStart={{ o2_install_path }}/{{ flpprototype_readoutcard_packagebasename }}/{{ flpprototype_readoutcard_packageversion }}/bin/roc-setup-hugetlbfs - -[Install] -WantedBy=multi-user.target diff --git a/hacking/example-config.yaml b/hacking/example-config.yaml deleted file mode 100644 index 2389e2794..000000000 --- a/hacking/example-config.yaml +++ /dev/null @@ -1,62 +0,0 @@ ---- -o2: - roleclasses: - readout: - wantsCPU: 1 - wantsMemory: 256 - wantsPorts: "" - command: - env: "[\"FOO=/bar/quux\", \"BAR=baz\"]" - shell: true -# value: source /etc/profile.d/modules.sh && \ -# MODULEPATH={{ o2_install_path }}/modulefiles module load {{ flpprototype_readout_packagebasename }}/{{ flpprototype_readout_packageversion }} && \ -# {{ o2_install_path }}/{{ flpprototype_readout_packagebasename }}/{{flpprototype_readout_packageversion}}/bin/o2-readout-exe file:{{ flpprototype_readout_confdir }}/{{ flpprototype_readout_default_config }} | {{ infologger_install_path }}/bin/log -x - value: source /etc/profile.d/modules.sh && - MODULEPATH=/opt/alisw/el7/modulefiles module load Readout && - /opt/alisw/el7/Readout/v0.1.0-16/bin/o2-readout-exe file:/etc/flpprototype.d/readout/configDummy.cfg | /opt/o2-InfoLogger/bin/o2-infologger-log -x - arguments: "[]" - qctask: - wantsCPU: 1 - wantsMemory: 256 - wantsPorts: "3000-3002" - command: - env: "[]" - shell: true - arguments: "[]" - value: source /etc/profile.d/modules.sh && - MODULEPATH=/opt/alisw/el7/modulefiles module load QualityControl && - MODULEPATH=/opt/alisw/el7/modulefiles module load Control-OCCPlugin && - MODULEPATH=/opt/alisw/el7/modulefiles module list && - qcTaskLauncher - -n myTask_1 -c json:///etc/flpprototype.d/qc/example-default.json - --id myTask_1 --mq-config /etc/flpprototype.d/qc/alfa.json - --severity trace --color false - -S $CONTROL_OCCPLUGIN_ROOT/lib/ - -P OCC --controlport 47101 - roles: - readout01: - roleClass: readout - qctask02: - roleClass: qctask - - - deployment: - o2_install_path: /opt/alisw/el7 - flpprototype_packagebasename: flpproto - flpprototype_packageversion: v0.1.0-16 - flpprototype_readout_confdir: /etc/flpprototype.d/readout - flpprototype_readout_default_config: configDummy.cfg - flpprototype_readout_packagebasename: Readout - flpprototype_readout_packageversion: v0.1.0-16 - flpprototype_readoutcard_packagebasename: ReadoutCard - flpprototype_readoutcard_packageversion: v0.8.7-1 - small_hugepages_count: 128 - large_hugepages_count: 0 - flpprototype_qc_confdir: /etc/flpprototype.d/qc - flpprototype_qc_default_config: example-default.ini - flpprototype_qc_fairmq_config: alfa.json - flpprototype_qc_packagebasename: QualityControl - flpprototype_qc_packageversion: v0.3.0-2 - infologger_install_path: /opt/o2-InfoLogger - infologger_confdir: /etc -