Changeset View
Changeset View
Standalone View
Standalone View
swh/icinga_plugins/save_code_now.py
- This file was added.
# Copyright (C) 2021 The Software Heritage developers | |||||
# See the AUTHORS file at the top-level directory of this distribution | |||||
# License: GNU General Public License version 3, or any later version | |||||
# See top-level LICENSE file for more information | |||||
import time | |||||
from typing import Dict, List | |||||
import requests | |||||
from .base_check import BaseCheck | |||||
REPORT_MSG = "Save code now request for origin" | |||||
WAITING_STATUSES = ("not yet scheduled", "running", "scheduled") | |||||
class SaveCodeNowCheck(BaseCheck): | |||||
TYPE = "SAVECODENOW" | |||||
DEFAULT_WARNING_THRESHOLD = 60 | |||||
DEFAULT_CRITICAL_THRESHOLD = 120 | |||||
def __init__(self, obj: Dict, origin: str, visit_type: str) -> None: | |||||
super().__init__(obj) | |||||
self.api_url = obj["swh_web_url"].rstrip("/") | |||||
self.poll_interval = obj["poll_interval"] | |||||
self.origin = origin | |||||
self.visit_type = visit_type | |||||
@staticmethod | |||||
def api_url_scn(root_api_url: str, origin: str, visit_type: str) -> str: | |||||
"""Compute the save code now api url for a given origin""" | |||||
return f"{root_api_url}/api/1/origin/save/{visit_type}/url/{origin}/" | |||||
def main(self) -> int: | |||||
"""Scenario description: | |||||
1. Requests a save code now request via the api for origin self.origin with type | |||||
self.visit_type. | |||||
2. Polling regularly at self.poll_interval seconds the completion status. | |||||
3. When either succeeded, failed or threshold exceeded, report approximate time | |||||
of completion. This will warn if thresholds are exceeded. | |||||
""" | |||||
start_time: float = time.time() | |||||
total_time: float = 0.0 | |||||
vsellier: lol | |||||
Done Inline Actions;) ardumont: ;) | |||||
scn_url = self.api_url_scn(self.api_url, self.origin, self.visit_type) | |||||
response = requests.post(scn_url) | |||||
assert response.status_code == 200, (response, response.text) | |||||
result: Dict = response.json() | |||||
status_key = "save_task_status" | |||||
request_date = result["save_request_date"] | |||||
origin_info = (self.visit_type, self.origin) | |||||
while result[status_key] in WAITING_STATUSES: | |||||
time.sleep(self.poll_interval) | |||||
response = requests.get(scn_url) | |||||
assert ( | |||||
response.status_code == 200 | |||||
), "Unexpected response: {response}, {response.text}" | |||||
raw_result: List[Dict] = response.json() | |||||
assert len(raw_result) > 0, f"Unexpected result: {raw_result}" | |||||
Done Inline Actionswill be replaced when the other part is fixed. ardumont: will be replaced when the other part is fixed. | |||||
if len(raw_result) > 1: | |||||
# retrieve only the one status result we are interested in | |||||
result = next( | |||||
filter(lambda r: r["save_request_date"] == request_date, raw_result) | |||||
Done Inline ActionsWe could try and randomly ask for picking up svn or hg mercurial origins which we did not do much over the last 3 months for example especially in staging... ardumont: We could try and randomly ask for picking up svn or hg mercurial origins which we did not do… | |||||
) | |||||
else: | |||||
result = raw_result[0] | |||||
# this because the api can return multiple entries for the same origin | |||||
assert result["save_request_date"] == request_date | |||||
total_time = time.time() - start_time | |||||
if total_time > self.critical_threshold: | |||||
self.print_result( | |||||
"CRITICAL", | |||||
f"{REPORT_MSG} {origin_info} took more than {total_time:.2f}s " | |||||
f'and has status: {result["save_task_status"]}.', | |||||
total_time=total_time, | |||||
) | |||||
return 2 | |||||
if result[status_key] == "succeeded": | |||||
(status_code, status) = self.get_status(total_time) | |||||
self.print_result( | |||||
status, | |||||
f"{REPORT_MSG} {origin_info} took {total_time:.2f}s and succeeded.", | |||||
total_time=total_time, | |||||
) | |||||
return status_code | |||||
elif result[status_key] == "failed": | |||||
self.print_result( | |||||
"CRITICAL", | |||||
f"{REPORT_MSG} {origin_info} took {total_time:.2f}s and failed.", | |||||
total_time=total_time, | |||||
) | |||||
return 2 | |||||
else: | |||||
self.print_result( | |||||
"CRITICAL", | |||||
f"{REPORT_MSG} {origin_info} took {total_time:.2f}s " | |||||
"and resulted in unsupported status: " | |||||
f"{result['save_request_status']} ; {result[status_key]}.", | |||||
total_time=total_time, | |||||
) | |||||
return 2 |
lol