Updated due to different af-green install issues
This commit is contained in:
parent
451f349904
commit
302282365e
@ -592,8 +592,20 @@ def manage_system_callable(**context):
|
|||||||
if not account_id: raise ValueError("An 'account_id' is required.")
|
if not account_id: raise ValueError("An 'account_id' is required.")
|
||||||
reason = f"Manual un-ban from Airflow mgmt DAG by {socket.gethostname()}"
|
reason = f"Manual un-ban from Airflow mgmt DAG by {socket.gethostname()}"
|
||||||
logger.info(f"Unbanning account '{account_id}'...")
|
logger.info(f"Unbanning account '{account_id}'...")
|
||||||
|
|
||||||
|
# Fetch status to get current success count before unbanning
|
||||||
|
statuses = client.getAccountStatus(accountId=account_id, accountPrefix=None)
|
||||||
|
if not statuses:
|
||||||
|
raise AirflowException(f"Account '{account_id}' not found.")
|
||||||
|
current_success_count = statuses[0].successCount or 0
|
||||||
|
|
||||||
client.unbanAccount(accountId=account_id, reason=reason)
|
client.unbanAccount(accountId=account_id, reason=reason)
|
||||||
print(f"Successfully sent request to unban account '{account_id}'.")
|
print(f"Successfully sent request to unban account '{account_id}'.")
|
||||||
|
|
||||||
|
# Set the success_count_at_activation to baseline the account
|
||||||
|
redis_client = _get_redis_client(params["redis_conn_id"])
|
||||||
|
redis_client.hset(f"account_status:{account_id}", "success_count_at_activation", current_success_count)
|
||||||
|
logger.info(f"Set 'success_count_at_activation' for '{account_id}' to {current_success_count}.")
|
||||||
elif action == "unban_all":
|
elif action == "unban_all":
|
||||||
account_prefix = account_id # Repurpose account_id param as an optional prefix
|
account_prefix = account_id # Repurpose account_id param as an optional prefix
|
||||||
logger.info(f"Unbanning all account statuses to ACTIVE (prefix: '{account_prefix or 'ALL'}')...")
|
logger.info(f"Unbanning all account statuses to ACTIVE (prefix: '{account_prefix or 'ALL'}')...")
|
||||||
@ -604,6 +616,9 @@ def manage_system_callable(**context):
|
|||||||
return
|
return
|
||||||
|
|
||||||
accounts_to_unban = [s.accountId for s in all_statuses]
|
accounts_to_unban = [s.accountId for s in all_statuses]
|
||||||
|
account_map = {s.accountId: s for s in all_statuses}
|
||||||
|
redis_client = _get_redis_client(params["redis_conn_id"])
|
||||||
|
|
||||||
logger.info(f"Found {len(accounts_to_unban)} accounts to unban.")
|
logger.info(f"Found {len(accounts_to_unban)} accounts to unban.")
|
||||||
print(f"Found {len(accounts_to_unban)} accounts. Sending unban request for each...")
|
print(f"Found {len(accounts_to_unban)} accounts. Sending unban request for each...")
|
||||||
|
|
||||||
@ -614,6 +629,12 @@ def manage_system_callable(**context):
|
|||||||
reason = f"Manual unban_all from Airflow mgmt DAG by {socket.gethostname()}"
|
reason = f"Manual unban_all from Airflow mgmt DAG by {socket.gethostname()}"
|
||||||
client.unbanAccount(accountId=acc_id, reason=reason)
|
client.unbanAccount(accountId=acc_id, reason=reason)
|
||||||
logger.info(f" - Sent unban for '{acc_id}'.")
|
logger.info(f" - Sent unban for '{acc_id}'.")
|
||||||
|
|
||||||
|
# Also set the success_count_at_activation to baseline the account
|
||||||
|
current_success_count = account_map[acc_id].successCount or 0
|
||||||
|
redis_client.hset(f"account_status:{acc_id}", "success_count_at_activation", current_success_count)
|
||||||
|
logger.info(f" - Set 'success_count_at_activation' for '{acc_id}' to {current_success_count}.")
|
||||||
|
|
||||||
unban_count += 1
|
unban_count += 1
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f" - Failed to unban account '{acc_id}': {e}")
|
logger.error(f" - Failed to unban account '{acc_id}': {e}")
|
||||||
@ -729,8 +750,20 @@ def manage_system_callable(**context):
|
|||||||
if not account_id: raise ValueError("An 'account_id' is required.")
|
if not account_id: raise ValueError("An 'account_id' is required.")
|
||||||
reason = f"Manual un-ban from Airflow mgmt DAG by {socket.gethostname()}"
|
reason = f"Manual un-ban from Airflow mgmt DAG by {socket.gethostname()}"
|
||||||
logger.info(f"Unbanning account '{account_id}'...")
|
logger.info(f"Unbanning account '{account_id}'...")
|
||||||
|
|
||||||
|
# Fetch status to get current success count before unbanning
|
||||||
|
statuses = client.getAccountStatus(accountId=account_id, accountPrefix=None)
|
||||||
|
if not statuses:
|
||||||
|
logger.warning(f"Account '{account_id}' not found. Skipping account unban.")
|
||||||
|
else:
|
||||||
|
current_success_count = statuses[0].successCount or 0
|
||||||
client.unbanAccount(accountId=account_id, reason=reason)
|
client.unbanAccount(accountId=account_id, reason=reason)
|
||||||
print(f"Successfully sent request to unban account '{account_id}'.")
|
print(f"Successfully sent request to unban account '{account_id}'.")
|
||||||
|
|
||||||
|
# Set the success_count_at_activation to baseline the account
|
||||||
|
redis_client = _get_redis_client(params["redis_conn_id"])
|
||||||
|
redis_client.hset(f"account_status:{account_id}", "success_count_at_activation", current_success_count)
|
||||||
|
logger.info(f"Set 'success_count_at_activation' for '{account_id}' to {current_success_count}.")
|
||||||
elif action == "unban_all":
|
elif action == "unban_all":
|
||||||
account_prefix = account_id # Repurpose account_id param as an optional prefix
|
account_prefix = account_id # Repurpose account_id param as an optional prefix
|
||||||
logger.info(f"Unbanning all account statuses to ACTIVE (prefix: '{account_prefix or 'ALL'}')...")
|
logger.info(f"Unbanning all account statuses to ACTIVE (prefix: '{account_prefix or 'ALL'}')...")
|
||||||
@ -740,6 +773,9 @@ def manage_system_callable(**context):
|
|||||||
print(f"No accounts found with prefix '{account_prefix or 'ALL'}' to unban.")
|
print(f"No accounts found with prefix '{account_prefix or 'ALL'}' to unban.")
|
||||||
else:
|
else:
|
||||||
accounts_to_unban = [s.accountId for s in all_statuses]
|
accounts_to_unban = [s.accountId for s in all_statuses]
|
||||||
|
account_map = {s.accountId: s for s in all_statuses}
|
||||||
|
redis_client = _get_redis_client(params["redis_conn_id"])
|
||||||
|
|
||||||
logger.info(f"Found {len(accounts_to_unban)} accounts to unban.")
|
logger.info(f"Found {len(accounts_to_unban)} accounts to unban.")
|
||||||
print(f"Found {len(accounts_to_unban)} accounts. Sending unban request for each...")
|
print(f"Found {len(accounts_to_unban)} accounts. Sending unban request for each...")
|
||||||
|
|
||||||
@ -750,6 +786,12 @@ def manage_system_callable(**context):
|
|||||||
reason = f"Manual unban_all from Airflow mgmt DAG by {socket.gethostname()}"
|
reason = f"Manual unban_all from Airflow mgmt DAG by {socket.gethostname()}"
|
||||||
client.unbanAccount(accountId=acc_id, reason=reason)
|
client.unbanAccount(accountId=acc_id, reason=reason)
|
||||||
logger.info(f" - Sent unban for '{acc_id}'.")
|
logger.info(f" - Sent unban for '{acc_id}'.")
|
||||||
|
|
||||||
|
# Also set the success_count_at_activation to baseline the account
|
||||||
|
current_success_count = account_map[acc_id].successCount or 0
|
||||||
|
redis_client.hset(f"account_status:{acc_id}", "success_count_at_activation", current_success_count)
|
||||||
|
logger.info(f" - Set 'success_count_at_activation' for '{acc_id}' to {current_success_count}.")
|
||||||
|
|
||||||
unban_count += 1
|
unban_count += 1
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f" - Failed to unban account '{acc_id}': {e}")
|
logger.error(f" - Failed to unban account '{acc_id}': {e}")
|
||||||
|
|||||||
@ -19,6 +19,7 @@ from airflow.models.param import Param
|
|||||||
from airflow.operators.python import PythonOperator, BranchPythonOperator
|
from airflow.operators.python import PythonOperator, BranchPythonOperator
|
||||||
from airflow.operators.empty import EmptyOperator
|
from airflow.operators.empty import EmptyOperator
|
||||||
from airflow.operators.bash import BashOperator
|
from airflow.operators.bash import BashOperator
|
||||||
|
from airflow.providers.celery.executors.celery_executor import app as celery_app
|
||||||
from airflow.providers.redis.hooks.redis import RedisHook
|
from airflow.providers.redis.hooks.redis import RedisHook
|
||||||
from airflow.utils.dates import days_ago
|
from airflow.utils.dates import days_ago
|
||||||
from airflow.models.variable import Variable
|
from airflow.models.variable import Variable
|
||||||
@ -535,6 +536,45 @@ def requeue_failed_callable(**context):
|
|||||||
raise AirflowException(f"Failed to requeue failed URLs: {e}")
|
raise AirflowException(f"Failed to requeue failed URLs: {e}")
|
||||||
|
|
||||||
|
|
||||||
|
def purge_celery_queue_callable(**context):
|
||||||
|
"""
|
||||||
|
Purges messages from the specified Celery queues using the Airflow Celery app.
|
||||||
|
This is more reliable than shelling out to `celery purge` as it uses the same
|
||||||
|
app context and broker connection as the workers.
|
||||||
|
"""
|
||||||
|
params = context['params']
|
||||||
|
if not params.get('confirm_purge'):
|
||||||
|
raise AirflowException("'Confirm Purge' is not checked. Aborting to prevent accidental data loss.")
|
||||||
|
|
||||||
|
queues_to_purge_str = params.get('celery_queue_to_purge')
|
||||||
|
if not queues_to_purge_str:
|
||||||
|
raise AirflowException("No Celery queues specified to purge.")
|
||||||
|
|
||||||
|
queues = [q.strip() for q in queues_to_purge_str.split(',') if q.strip()]
|
||||||
|
|
||||||
|
logger.info(f"Attempting to purge {len(queues)} Celery queue(s): {queues}")
|
||||||
|
logger.info(f"Using broker: {celery_app.conf.broker_url}")
|
||||||
|
|
||||||
|
purged_counts = {}
|
||||||
|
with celery_app.connection_for_read() as conn:
|
||||||
|
with conn.channel() as channel:
|
||||||
|
for queue in queues:
|
||||||
|
try:
|
||||||
|
message_count = channel.queue_purge(queue)
|
||||||
|
purged_counts[queue] = message_count
|
||||||
|
logger.info(f"Purged {message_count} messages from queue '{queue}'.")
|
||||||
|
except Exception as e:
|
||||||
|
# This can happen if the queue doesn't exist on the broker.
|
||||||
|
# kombu might raise an operational error.
|
||||||
|
logger.error(f"Failed to purge queue '{queue}': {e}", exc_info=True)
|
||||||
|
purged_counts[queue] = f"ERROR: {e}"
|
||||||
|
|
||||||
|
logger.info("--- Celery Purge Summary ---")
|
||||||
|
for queue, result in purged_counts.items():
|
||||||
|
logger.info(f" - {queue}: {result}")
|
||||||
|
logger.info("--- Purge complete. ---")
|
||||||
|
|
||||||
|
|
||||||
def add_videos_to_queue_callable(**context):
|
def add_videos_to_queue_callable(**context):
|
||||||
"""
|
"""
|
||||||
Parses video inputs from manual text, a predefined file, or a file path/URL,
|
Parses video inputs from manual text, a predefined file, or a file path/URL,
|
||||||
@ -821,32 +861,9 @@ with DAG(
|
|||||||
""",
|
""",
|
||||||
)
|
)
|
||||||
|
|
||||||
action_purge_celery_queue = BashOperator(
|
action_purge_celery_queue = PythonOperator(
|
||||||
task_id="action_purge_celery_queue",
|
task_id="action_purge_celery_queue",
|
||||||
bash_command="""
|
python_callable=purge_celery_queue_callable,
|
||||||
if [ "{{ params.confirm_purge }}" != "True" ]; then
|
|
||||||
echo "ERROR: 'Confirm Purge' is not checked. Aborting to prevent accidental data loss."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
BROKER_URL=$(airflow config get-value celery broker_url)
|
|
||||||
QUEUES_TO_PURGE="{{ params.celery_queue_to_purge }}"
|
|
||||||
|
|
||||||
if [ -z "$QUEUES_TO_PURGE" ]; then
|
|
||||||
echo "ERROR: No Celery queues specified to purge."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "--- Purging Celery Queues (Broker: $BROKER_URL) ---"
|
|
||||||
|
|
||||||
# Use tr to convert comma-separated string to space-separated for the loop
|
|
||||||
for Q in $(echo $QUEUES_TO_PURGE | tr ',' ' '); do
|
|
||||||
echo "Purging queue: $Q"
|
|
||||||
celery -A airflow.providers.celery.executors.celery_executor.app -b "$BROKER_URL" purge -f -Q "$Q"
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "--- Purge command sent for all specified queues. ---"
|
|
||||||
""",
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# --- Wire up tasks ---
|
# --- Wire up tasks ---
|
||||||
|
|||||||
@ -147,10 +147,17 @@ def manage_account_states(**context):
|
|||||||
logger.info("--- Step 3: Processing un-bans ---")
|
logger.info("--- Step 3: Processing un-bans ---")
|
||||||
if accounts_to_unban:
|
if accounts_to_unban:
|
||||||
logger.info(f"Un-banning {len(accounts_to_unban)} accounts: {accounts_to_unban}")
|
logger.info(f"Un-banning {len(accounts_to_unban)} accounts: {accounts_to_unban}")
|
||||||
|
account_map = {acc.accountId: acc for acc in all_accounts}
|
||||||
for acc_id in accounts_to_unban:
|
for acc_id in accounts_to_unban:
|
||||||
try:
|
try:
|
||||||
client.unbanAccount(acc_id, "Automatic un-ban by Airflow maintenance DAG.")
|
client.unbanAccount(acc_id, "Automatic un-ban by Airflow maintenance DAG.")
|
||||||
logger.info(f"Successfully un-banned account '{acc_id}'.")
|
logger.info(f"Successfully un-banned account '{acc_id}'.")
|
||||||
|
|
||||||
|
# Set the activation count to baseline the account immediately after un-banning.
|
||||||
|
key = f"account_status:{acc_id}"
|
||||||
|
current_success_count = account_map[acc_id].successCount or 0
|
||||||
|
redis_client.hset(key, "success_count_at_activation", current_success_count)
|
||||||
|
logger.info(f"Set 'success_count_at_activation' for un-banned account '{acc_id}' to {current_success_count}.")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Failed to un-ban account '{acc_id}': {e}")
|
logger.error(f"Failed to un-ban account '{acc_id}': {e}")
|
||||||
else:
|
else:
|
||||||
|
|||||||
@ -25,7 +25,6 @@
|
|||||||
- thrift
|
- thrift
|
||||||
- aria2p
|
- aria2p
|
||||||
- PyYAML
|
- PyYAML
|
||||||
- apache-airflow-providers-amazon
|
|
||||||
state: present
|
state: present
|
||||||
become: yes
|
become: yes
|
||||||
|
|
||||||
@ -279,20 +278,23 @@
|
|||||||
var: config_generator_result.stdout_lines
|
var: config_generator_result.stdout_lines
|
||||||
when: config_generator_result.changed
|
when: config_generator_result.changed
|
||||||
|
|
||||||
- name: Start ytdlp-ops services on master
|
|
||||||
community.docker.docker_compose_v2:
|
|
||||||
project_src: "{{ airflow_master_dir }}"
|
|
||||||
files:
|
|
||||||
- configs/docker-compose-ytdlp-ops.yaml
|
|
||||||
state: present
|
|
||||||
remove_orphans: true
|
|
||||||
pull: "{{ 'never' if fast_deploy | default(false) else 'missing' }}"
|
|
||||||
|
|
||||||
roles:
|
roles:
|
||||||
- ytdlp-master
|
- ytdlp-master
|
||||||
- airflow-master
|
- airflow-master
|
||||||
|
|
||||||
post_tasks:
|
post_tasks:
|
||||||
|
- name: Wait for airflow-scheduler to be running before proceeding
|
||||||
|
ansible.builtin.command: docker compose ps --filter "status=running" --services
|
||||||
|
args:
|
||||||
|
chdir: "{{ airflow_master_dir }}"
|
||||||
|
register: running_services
|
||||||
|
until: "'airflow-scheduler' in running_services.stdout_lines"
|
||||||
|
retries: 30
|
||||||
|
delay: 10
|
||||||
|
changed_when: false
|
||||||
|
become: yes
|
||||||
|
become_user: "{{ ansible_user }}"
|
||||||
|
|
||||||
- name: Delete existing Airflow redis_default connection to ensure an idempotent update
|
- name: Delete existing Airflow redis_default connection to ensure an idempotent update
|
||||||
ansible.builtin.command: >
|
ansible.builtin.command: >
|
||||||
docker compose exec -T airflow-scheduler
|
docker compose exec -T airflow-scheduler
|
||||||
|
|||||||
@ -102,13 +102,7 @@
|
|||||||
dest: "{{ airflow_worker_dir }}/{{ item }}"
|
dest: "{{ airflow_worker_dir }}/{{ item }}"
|
||||||
perms: yes
|
perms: yes
|
||||||
loop:
|
loop:
|
||||||
- "README.client.md"
|
|
||||||
- "cli.config"
|
- "cli.config"
|
||||||
- "format_download.py"
|
|
||||||
- "get_info_json_client.py"
|
|
||||||
- "list_formats.py"
|
|
||||||
- "stress_test_formats.py"
|
|
||||||
- "stress_enhanced.py"
|
|
||||||
- "package_client.py"
|
- "package_client.py"
|
||||||
- "bin/ytops-client"
|
- "bin/ytops-client"
|
||||||
become: yes
|
become: yes
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
---
|
---
|
||||||
- name: Update S3 Delivery Airflow Connection
|
- name: Update S3 Connection Variable
|
||||||
hosts: airflow_master
|
hosts: airflow_master
|
||||||
|
gather_facts: no
|
||||||
vars_files:
|
vars_files:
|
||||||
- "{{ inventory_dir }}/group_vars/all/vault.yml"
|
|
||||||
- "{{ inventory_dir }}/group_vars/all/generated_vars.yml"
|
- "{{ inventory_dir }}/group_vars/all/generated_vars.yml"
|
||||||
|
- "{{ inventory_dir }}/group_vars/all/vault.yml"
|
||||||
tasks:
|
tasks:
|
||||||
- name: Delete existing s3_delivery_connection to ensure an idempotent update
|
- name: Delete existing s3_delivery_connection to ensure an idempotent update
|
||||||
ansible.builtin.command: >
|
ansible.builtin.command: >
|
||||||
|
|||||||
@ -17,12 +17,6 @@
|
|||||||
mode: '0755'
|
mode: '0755'
|
||||||
become: yes
|
become: yes
|
||||||
|
|
||||||
- name: "Copy get_info_json_client.py to worker"
|
|
||||||
ansible.builtin.copy:
|
|
||||||
src: ../../get_info_json_client.py
|
|
||||||
dest: "{{ project_dir }}/get_info_json_client.py"
|
|
||||||
mode: '0755'
|
|
||||||
become: yes
|
|
||||||
|
|
||||||
- name: "Pull the latest image for the ytdlp-ops service"
|
- name: "Pull the latest image for the ytdlp-ops service"
|
||||||
community.docker.docker_image:
|
community.docker.docker_image:
|
||||||
|
|||||||
@ -81,7 +81,6 @@
|
|||||||
- "thrift_model"
|
- "thrift_model"
|
||||||
- "VERSION"
|
- "VERSION"
|
||||||
- "airflow/update-yt-dlp.sh"
|
- "airflow/update-yt-dlp.sh"
|
||||||
- "get_info_json_client.py"
|
|
||||||
- "proxy_manager_client.py"
|
- "proxy_manager_client.py"
|
||||||
- "utils"
|
- "utils"
|
||||||
|
|
||||||
@ -328,6 +327,7 @@
|
|||||||
project_src: "{{ airflow_master_dir }}"
|
project_src: "{{ airflow_master_dir }}"
|
||||||
files:
|
files:
|
||||||
- "configs/docker-compose-master.yaml"
|
- "configs/docker-compose-master.yaml"
|
||||||
|
- "configs/docker-compose-ytdlp-ops.yaml"
|
||||||
state: present
|
state: present
|
||||||
remove_orphans: true
|
remove_orphans: true
|
||||||
pull: "{{ 'never' if fast_deploy | default(false) else 'missing' }}"
|
pull: "{{ 'never' if fast_deploy | default(false) else 'missing' }}"
|
||||||
|
|||||||
@ -71,7 +71,6 @@
|
|||||||
- "thrift_model"
|
- "thrift_model"
|
||||||
- "VERSION"
|
- "VERSION"
|
||||||
- "airflow/update-yt-dlp.sh"
|
- "airflow/update-yt-dlp.sh"
|
||||||
- "get_info_json_client.py"
|
|
||||||
- "proxy_manager_client.py"
|
- "proxy_manager_client.py"
|
||||||
- "utils"
|
- "utils"
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user