diff --git a/README.md b/README.md index 99036f0b7db851d716248d3042979e500f982993..04ee72b45110c17ca595613e1a88d1792e2ffde0 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,7 @@ order: - `ansible-playbook 02_install_nvidia_driver_*.yml` - `ansible-playbook 03_install_mellanox_ofed.yml` - `ansible-playbook 04_install_slurm.yml` +- `ansible-playbook xx_merge_users.yml` ### Playbook overview @@ -63,5 +64,10 @@ order: - **03_install_mellanox_ofed.yml**\ Installs Mellanox OFED drivers. -- **04\_ install_slurm.yml**\ +- **04_install_slurm.yml**\ Installs and configures SLURM for use with DAS-6. + +- **xx_merge_users.yml**\ + Merges the system users from the local machine with the users from DAS-6. This + playbook has number `xx` because it should preferably be ran periodically, + e.g. using cron. diff --git a/templates/merge_users.sh b/templates/merge_users.sh new file mode 100644 index 0000000000000000000000000000000000000000..848165590dc850c4498bc41157f7615e5181e1df --- /dev/null +++ b/templates/merge_users.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +set -e + +SOURCE_DIR=$1 +DEST_DIR=$2 + +for file in passwd group shadow; do + SOURCE_FILE="${SOURCE_DIR}/${file}_src" + DEST_FILE="${DEST_DIR}/${file}" + MERGED_FILE="${SOURCE_DIR}/merged_${file}" + + # Ensure files exist + if [[ ! -f "$SOURCE_FILE" || ! -f "$DEST_FILE" ]]; then + echo "Error: One of the source or destination files is missing!" + exit 1 + fi + + # Extract users + awk -F: '$3 < 1000' "$DEST_FILE" > "$MERGED_FILE" # System users from target + awk -F: '$3 >= 1000' "$SOURCE_FILE" >> "$MERGED_FILE" # Normal users from source + + # Ensure uniqueness and sort + sort -t: -k1,1 -u -o "$MERGED_FILE" "$MERGED_FILE" +done + diff --git a/xx_merge_users.yml b/xx_merge_users.yml new file mode 100644 index 0000000000000000000000000000000000000000..ec2bd2e03fd88bb0928888423d7d11f1eaf0a360 --- /dev/null +++ b/xx_merge_users.yml @@ -0,0 +1,54 @@ +- name: Merge passwd, group, and shadow files from fs5 to target system + hosts: localhost + become: true + vars: + root_host: fs5 + files: + - {name: "passwd", mode: "0644"} + - {name: "group", mode: "0644"} + - {name: "shadow", mode: "0600"} + local_temp_dir: /tmp/user_merge + remote_etc_dir: /etc + tasks: + - name: Ensure local temporary directory exists + file: + path: "{{ local_temp_dir }}" + state: directory + mode: '0755' + - name: Fetch user-related files from fs5 + fetch: + src: "{{ remote_etc_dir }}/{{ item.name }}" + dest: "{{ local_temp_dir }}/{{ item.name }}_fs5" + flat: true + loop: "{{ files }}" + delegate_to: "{{ root_host }}" + vars: + ansible_ssh_common_args: "-o StrictHostKeyChecking=no" + - name: Read current target system files + slurp: + src: "{{ remote_etc_dir }}/{{ item.name }}" + register: target_files + loop: "{{ files }}" + - name: Generate user merge script + template: + src: merge_users.sh + dest: "{{ local_temp_dir }}/merge_users.sh" + mode: '0755' + - name: Execute merge script + command: "{{ local_temp_dir }}/merge_users.sh {{ local_temp_dir }} {{ remote_etc_dir }}" + register: merge_output + changed_when: merge_output.rc == 0 + - name: Replace files if changed + copy: + src: "{{ local_temp_dir }}/merged_{{ item.name }}" + dest: "{{ remote_etc_dir }}/{{ item.name }}" + owner: root + group: root + mode: "{{ item.mode }}" + backup: true + when: target_files.results | selectattr('item.name', 'equalto', item.name) | map(attribute='content') | map('b64decode') | first != lookup('file', '{{ local_temp_dir }}/merged_{{ item.name }}') + loop: "{{ files }}" + - name: Clean up temporary files + file: + path: "{{ local_temp_dir }}" + state: absent