diff --git a/mirrors/files/linux-mint/images/confd/mintUpdateImages.service b/mirrors/files/linux-mint/images/confd/mintUpdateImages.service new file mode 100644 index 0000000..1ce675d --- /dev/null +++ b/mirrors/files/linux-mint/images/confd/mintUpdateImages.service @@ -0,0 +1,10 @@ +[Unit] +Description=Keeping the linux mint mirror images up to date +After=network-online.target +Wants=network-online.target + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/linux-mint-sync-images.sh +TimeoutStartSec=7200 +User=mirrors \ No newline at end of file diff --git a/mirrors/files/linux-mint/images/confd/mintUpdateImages.timer b/mirrors/files/linux-mint/images/confd/mintUpdateImages.timer new file mode 100644 index 0000000..d12e761 --- /dev/null +++ b/mirrors/files/linux-mint/images/confd/mintUpdateImages.timer @@ -0,0 +1,10 @@ +[Unit] +Description=Activate service for syncing changes in the linux mint mirror + +[Timer] +OnCalendar=*:0/15 +AccuracySec=5m +Persistent=true + +[Install] +WantedBy=timers.target \ No newline at end of file diff --git a/mirrors/files/linux-mint/images/scripts/linux-mint-sync-images.sh b/mirrors/files/linux-mint/images/scripts/linux-mint-sync-images.sh new file mode 100644 index 0000000..f44e55c --- /dev/null +++ b/mirrors/files/linux-mint/images/scripts/linux-mint-sync-images.sh @@ -0,0 +1,126 @@ +#!/bin/bash + +# This script checks the status of the upstream Linux Mint server and the local mirror. +# It compares the last modification time of a reference file +# and checks the following conditions: +# +# - If the upstream mirror has new updates, the local mirror fetches them +# - If the upstream mirror was updated less than 24 hours ago, the local mirror is considered up-to-date and no action is taken. +# - If the upstream mirror was updated more than 24 hours ago it synchronizes again +# +# This script is intended to be run repeatedly by a cron job or a systemd timer. + + +MIRROR_DIRECTORY=/srv/linux-mint +LOCAL_MIRROR="lidsol.fi-b.unam.mx" +MIRROR_DIRECTORY_SO=${MIRROR_DIRECTORY}/images +LATEST_UPDATE_FILE=latest_sync_images.meta + +mkdir -p ${MIRROR_DIRECTORY_SO} + +MAIN_SERVER_URL=https://pub.linuxmint.io +MAIN_SERVER_RSYNC=pub.linuxmint.com::pub +function get_upstream_time(){ + dates=() + while IFS= read -r line; do + dates+=("$line") + done < <(curl -s --compressed "$MAIN_SERVER_URL" \ + | grep -Eo '[0-9]{2}-[A-Za-z]{3}-[0-9]{4} [0-9]{2}:[0-9]{2}') + local latest="" + local latest_epoch=0 + #In case we don't receive any date for connection problems + if [ ${#dates[@]} -eq 0 ]; then + echo "1970-01-01 00:00:00 UTC" + return + fi + + for d in "${dates[@]}"; do + converted_date=$(echo "$d" | awk '{ + split($1, parts, "-") + day = parts[1] + month = parts[2] + year = parts[3] + time = $2 + + # Convert month name to number + if (month == "Jan") month = "01" + else if (month == "Feb") month = "02" + else if (month == "Mar") month = "03" + else if (month == "Apr") month = "04" + else if (month == "May") month = "05" + else if (month == "Jun") month = "06" + else if (month == "Jul") month = "07" + else if (month == "Aug") month = "08" + else if (month == "Sep") month = "09" + else if (month == "Oct") month = "10" + else if (month == "Nov") month = "11" + else if (month == "Dec") month = "12" + + printf "%s-%s-%s %s:00", year, month, day, time + }') + epoch=$(date -d "$converted_date" +"%s" 2>/dev/null) + if [[ $? -eq 0 && $epoch -gt $latest_epoch ]]; then + latest_epoch=$epoch + latest="$converted_date" + fi + done + + echo "$latest" +} + +function get_local_time() { + if [ -f ${MIRROR_DIRECTORY}/${LATEST_UPDATE_FILE} ]; then + cat ${MIRROR_DIRECTORY}/${LATEST_UPDATE_FILE} | head -n 1 + else + echo "1970-01-01 00:00:00 UTC" >${MIRROR_DIRECTORY}/${LATEST_UPDATE_FILE} + echo "1970-01-01 00:00:00 UTC" + fi +} + +function should_pull() +{ + local_mirror_time=$1 + upstream_time=$2 + current_time=$3 + # Log input of function to stderr + local_mirror_time_epoch=$(date -d "$local_mirror_time" +%s) + upstream_time_epoch=$(date -d "$upstream_time" +%s) + current_time_epoch=$(date -d "$current_time" +%s) + + + if [ $(($current_time_epoch - $local_mirror_time_epoch)) -gt 86400 ]; then + echo "true" + return + fi + + + if [ $(($current_time_epoch - $local_mirror_time_epoch)) -lt 43200 ]; then + + echo "false" + return + fi + + # If the local mirror is older than the upstream mirror, then the local mirror + # is considered out of date + if [ $local_mirror_time_epoch -lt $upstream_time_epoch ]; then + echo "true" + else + echo "false" + fi +} + +if [ $(should_pull "$(get_local_time)" "$(get_upstream_time)" "$(date -u)") == "true" ]; then + echo "Local mirror is out of date, pulling from upstream mirror. Upstream date: $(get_upstream_time), Local date: $(get_local_time) - current date: $(date -u)" + new_date="$(date -u '+%Y-%m-%d %H:%M:%S UTC')" + if rsync -av --delete --partial \ + ${MAIN_SERVER_RSYNC} ${MIRROR_DIRECTORY_SO}; then + sed -i "1s/.*/$new_date/" ${MIRROR_DIRECTORY}/${LATEST_UPDATE_FILE} + else + echo "Error: rsync failed" + exit 1 + fi + + +else + echo "Local mirror is up to date. Upstream date: $(get_upstream_time), Local date: $(get_local_time) - current date: $(date -u)" +fi diff --git a/mirrors/files/linux-mint/repository/confd/mintUpdateRepository.service b/mirrors/files/linux-mint/repository/confd/mintUpdateRepository.service new file mode 100644 index 0000000..c79d98c --- /dev/null +++ b/mirrors/files/linux-mint/repository/confd/mintUpdateRepository.service @@ -0,0 +1,10 @@ +[Unit] +Description=Keeping the linux mint mirror repository up to date +After=network-online.target +Wants=network-online.target + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/linux-mint-sync-repo.sh +TimeoutStartSec=1800 +User=mirrors \ No newline at end of file diff --git a/mirrors/files/linux-mint/repository/confd/mintUpdateRepository.timer b/mirrors/files/linux-mint/repository/confd/mintUpdateRepository.timer new file mode 100644 index 0000000..d12e761 --- /dev/null +++ b/mirrors/files/linux-mint/repository/confd/mintUpdateRepository.timer @@ -0,0 +1,10 @@ +[Unit] +Description=Activate service for syncing changes in the linux mint mirror + +[Timer] +OnCalendar=*:0/15 +AccuracySec=5m +Persistent=true + +[Install] +WantedBy=timers.target \ No newline at end of file diff --git a/mirrors/files/linux-mint/repository/scripts/linux-mint-sync-repo.sh b/mirrors/files/linux-mint/repository/scripts/linux-mint-sync-repo.sh new file mode 100644 index 0000000..833e7c0 --- /dev/null +++ b/mirrors/files/linux-mint/repository/scripts/linux-mint-sync-repo.sh @@ -0,0 +1,108 @@ +#!/bin/bash + + +# This script checks the status of the upstream Linux Mint server and the local mirror. +# It compares the last modification time of a reference file +# and checks the following conditions: +# +# - If the upstream mirror has new updates, the local mirror fetches them +# - If the upstream mirror was updated less than 24 hours ago, the local mirror is considered up-to-date and no action is taken. +# - If the upstream mirror was updated more than 24 hours ago it synchronizes again +# +# This script is intended to be run repeatedly by a cron job or a systemd timer. + + +MIRROR_DIRECTORY=/srv/linux-mint +LOCAL_MIRROR="lidsol.fi-b.unam.mx" +MIRROR_DIRECTORY_RP=${MIRROR_DIRECTORY}/repository +LATEST_UPDATE_FILE=latest_sync_repository.meta +mkdir -p ${MIRROR_DIRECTORY_RP} + +MIRROR_SERVER_URL=https://mirrors.seas.harvard.edu/linuxmint-packages/ +MAIN_SERVER_RSYNC=rsync-packages.linuxmint.com::packages +function get_upstream_time(){ + dates=() + while IFS= read -r line; do + dates+=("$line") + done < <(curl -s --compressed ${MIRROR_SERVER_URL} | grep -Eo '[0-9]{4}-(0[1-9]|1[0-2])-[0-9]{2} [0-9]{2}:[0-9]{2}') + local latest="" + local latest_epoch=0 + # In case we don't receive any date for connection problems + if [ ${#dates[@]} -eq 0 ]; then + echo "1970-01-01 00:00:00 UTC" + return + fi + + for d in "${dates[@]}"; do + converted_date=$d + epoch=$(date -d "$converted_date" +"%s" 2>/dev/null) + if [[ $? -eq 0 && $epoch -gt $latest_epoch ]]; then + latest_epoch=$epoch + latest="$converted_date" + fi + done + + echo "${latest}:00 UTC" +} + +function get_local_time() { + if [ -f ${MIRROR_DIRECTORY}/${LATEST_UPDATE_FILE} ]; then + cat ${MIRROR_DIRECTORY}/${LATEST_UPDATE_FILE} | head -n 1 + else + echo "1970-01-01 00:00:00 UTC" >${MIRROR_DIRECTORY}/${LATEST_UPDATE_FILE} + echo "1970-01-01 00:00:00 UTC" + fi +} + +function should_pull() +{ + local_mirror_time=$1 + upstream_time=$2 + current_time=$3 + # Log input of function to stderr + local_mirror_time_epoch=$(date -d "$local_mirror_time" +%s) + upstream_time_epoch=$(date -d "$upstream_time" +%s) + current_time_epoch=$(date -d "$current_time" +%s) + + # If the local mirror is more than 12 hours old, then the mirror is considered out of date + if [ $(($current_time_epoch - $local_mirror_time_epoch)) -gt 43200 ]; then + echo "true" + return + fi + + # If it has been less than 12 hours since the upstream mirror started updating, + # then the mirror is considered up-to-date + if [ $(($current_time_epoch - $local_mirror_time_epoch)) -lt 21600 ]; then + # Log the operation above to stderr + echo "false" + return + fi + + # If the local mirror is older than the upstream mirror, then the local mirror + # is considered out of date + if [ $local_mirror_time_epoch -lt $upstream_time_epoch ]; then + echo "true" + else + echo "false" + fi +} + +if [ $(should_pull "$(get_local_time)" "$(get_upstream_time)" "$(date -u)") == "true" ]; then + echo "Local mirror is out of date, pulling from upstream mirror. Upstream date: $(get_upstream_time), Local date: $(get_local_time) - current date: $(date -u)" + new_date="$(date -u '+%Y-%m-%d %H:%M:%S UTC')" + if rsync -av --delete --partial \ + ${MAIN_SERVER_RSYNC} ${MIRROR_DIRECTORY_RP}; then + sed -i "1s/.*/$new_date/" ${MIRROR_DIRECTORY}/${LATEST_UPDATE_FILE} + else + echo "Error: rsync failed" + exit 1 + fi + +else + echo "Local mirror is up to date. Upstream date: $(get_upstream_time), Local date: $(get_local_time) - current date: $(date -u)" +fi + + + + + diff --git a/mirrors/hosts.ini b/mirrors/hosts.ini new file mode 100644 index 0000000..0ff6487 --- /dev/null +++ b/mirrors/hosts.ini @@ -0,0 +1,2 @@ +[mirror-server] +lidsol.fi-b.unam.mx diff --git a/mirrors/main.yml b/mirrors/main.yml new file mode 100644 index 0000000..aa749c8 --- /dev/null +++ b/mirrors/main.yml @@ -0,0 +1,9 @@ +--- +- name: Setup mirrors server for LIDSoL + hosts: mirror-server + become: true + + tasks: + - name: Linux Mint mirrors + ansible.builtin.import_tasks: tasks/linux-mint.yaml + diff --git a/mirrors/tasks/linux-mint.yaml b/mirrors/tasks/linux-mint.yaml new file mode 100644 index 0000000..014f7f8 --- /dev/null +++ b/mirrors/tasks/linux-mint.yaml @@ -0,0 +1,51 @@ +# Ansible task file for setting up Linux Mint mirrors +# This playbook copies necessary service and script files to the target system +# and ensures that the corresponding systemd services and timers are enabled and started. +--- +- name: Copy required systemd service and timer files for linux mint images mirror + ansible.builtin.copy: + src: files/linux-mint/images/confd/{{ item }} + dest: /etc/systemd/system/{{ item }} + owner: root + group: root + mode: '0644' + loop: + - "mintUpdateImages.service" + - "mintUpdateImages.timer" + +- name: Copy linux mint sync script for images mirror + ansible.builtin.copy: + src: files/linux-mint/images/scripts/linux-mint-sync-images.sh + dest: /usr/local/bin/linux-mint-sync-images.sh + owner: root + group: root + mode: '0755' + +- name: Copy required systemd service and timer files for linux mint repository mirror + ansible.builtin.copy: + src: files/linux-mint/repository/confd/{{ item }} + dest: /etc/systemd/system/{{ item }} + owner: root + group: root + mode: '0644' + loop: + - "mintUpdateRepository.service" + - "mintUpdateRepository.timer" + +- name: Copy linux mint sync script for repository mirror + ansible.builtin.copy: + src: files/linux-mint/repository/scripts/linux-mint-sync-repo.sh + dest: /usr/local/bin/linux-mint-sync-repo.sh + owner: root + group: root + mode: '0755' + +- name: Start timer service for linux mint mirrors + ansible.builtin.systemd_service: + name: "{{ item }}" + enabled: true + state: started + daemon_reload: true + loop: + - "mintUpdateImages.timer" + - "mintUpdateRepository.timer"