forked from mirrors/gecko-dev
MozReview-Commit-ID: 9nj7qe5hWa9 --HG-- extra : rebase_source : 1c6a9515a7cc5fd1b5c3482a6806bcc69bbbb5dd
189 lines
7.4 KiB
Python
189 lines
7.4 KiB
Python
#!/usr/bin/env python
|
|
# lint_ignore=E501
|
|
# ***** BEGIN LICENSE BLOCK *****
|
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
# You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
# ***** END LICENSE BLOCK *****
|
|
""" uptake_monitoring.py
|
|
|
|
A script to replace the old-fashion way of computing the uptake monitoring
|
|
from the scheduler within the slaves.
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import datetime
|
|
import time
|
|
import xml.dom.minidom
|
|
|
|
sys.path.insert(1, os.path.dirname(os.path.dirname(sys.path[0])))
|
|
|
|
from mozharness.base.python import VirtualenvMixin, virtualenv_config_options
|
|
from mozharness.base.script import BaseScript
|
|
from mozharness.mozilla.buildbot import BuildbotMixin
|
|
|
|
|
|
def get_tuxedo_uptake_url(tuxedo_server_url, related_product, os):
|
|
return '%s/uptake/?product=%s&os=%s' % (tuxedo_server_url,
|
|
related_product, os)
|
|
|
|
|
|
class UptakeMonitoring(BaseScript, VirtualenvMixin, BuildbotMixin):
|
|
config_options = virtualenv_config_options
|
|
|
|
def __init__(self, require_config_file=True):
|
|
super(UptakeMonitoring, self).__init__(
|
|
config_options=self.config_options,
|
|
require_config_file=require_config_file,
|
|
config={
|
|
"virtualenv_modules": [
|
|
"redo",
|
|
"requests",
|
|
],
|
|
|
|
"virtualenv_path": "venv",
|
|
"credentials_file": "oauth.txt",
|
|
"buildbot_json_path": "buildprops.json",
|
|
"poll_interval": 60,
|
|
"poll_timeout": 20*60,
|
|
"min_uptake": 10000,
|
|
},
|
|
all_actions=[
|
|
"create-virtualenv",
|
|
"activate-virtualenv",
|
|
"monitor-uptake",
|
|
],
|
|
default_actions=[
|
|
"create-virtualenv",
|
|
"activate-virtualenv",
|
|
"monitor-uptake",
|
|
],
|
|
)
|
|
|
|
def _pre_config_lock(self, rw_config):
|
|
super(UptakeMonitoring, self)._pre_config_lock(rw_config)
|
|
# override properties from buildbot properties here as defined by
|
|
# taskcluster properties
|
|
self.read_buildbot_config()
|
|
if not self.buildbot_config:
|
|
self.warning("Skipping buildbot properties overrides")
|
|
return
|
|
props = self.buildbot_config["properties"]
|
|
for prop in ['tuxedo_server_url', 'version']:
|
|
if props.get(prop):
|
|
self.info("Overriding %s with %s" % (prop, props[prop]))
|
|
self.config[prop] = props.get(prop)
|
|
else:
|
|
self.warning("%s could not be found within buildprops" % prop)
|
|
return
|
|
if props.get('partial_versions'):
|
|
partials = [v.strip() for v in props["partial_versions"].split(",")]
|
|
self.config["partial_versions"] = [v.split("build")[0] for v in partials]
|
|
self.config["platforms"] = [p.strip() for p in
|
|
props["platforms"].split(",")]
|
|
|
|
def _get_product_uptake(self, tuxedo_server_url, auth,
|
|
related_product, os):
|
|
from redo import retry
|
|
import requests
|
|
|
|
url = get_tuxedo_uptake_url(tuxedo_server_url, related_product, os)
|
|
self.info("Requesting {} from tuxedo".format(url))
|
|
|
|
def get_tuxedo_page():
|
|
r = requests.get(url, auth=auth,
|
|
verify=False, timeout=60)
|
|
r.raise_for_status()
|
|
return r.content
|
|
|
|
def calculateUptake(page):
|
|
doc = xml.dom.minidom.parseString(page)
|
|
uptake_values = []
|
|
|
|
for element in doc.getElementsByTagName('available'):
|
|
for node in element.childNodes:
|
|
if node.nodeType == xml.dom.minidom.Node.TEXT_NODE and \
|
|
node.data.isdigit():
|
|
uptake_values.append(int(node.data))
|
|
if not uptake_values:
|
|
uptake_values = [0]
|
|
return min(uptake_values)
|
|
|
|
page = retry(get_tuxedo_page)
|
|
uptake = calculateUptake(page)
|
|
self.info("Current uptake for {} is {}".format(related_product, uptake))
|
|
return uptake
|
|
|
|
def _get_release_uptake(self, auth):
|
|
assert isinstance(self.config["platforms"], (list, tuple))
|
|
|
|
# handle the products first
|
|
tuxedo_server_url = self.config["tuxedo_server_url"]
|
|
version = self.config["version"]
|
|
dl = []
|
|
|
|
for product, info in self.config["products"].iteritems():
|
|
if info.get("check_uptake"):
|
|
product_template = info["product-name"]
|
|
related_product = product_template % {"version": version}
|
|
|
|
enUS_platforms = set(self.config["platforms"])
|
|
paths_platforms = set(info["paths"].keys())
|
|
platforms = enUS_platforms.intersection(paths_platforms)
|
|
|
|
for platform in platforms:
|
|
bouncer_platform = info["paths"].get(platform).get('bouncer-platform')
|
|
dl.append(self._get_product_uptake(tuxedo_server_url, auth,
|
|
related_product, bouncer_platform))
|
|
# handle the partials as well
|
|
prev_versions = self.config.get("partial_versions", [])
|
|
for product, info in self.config.get("partials", {}).iteritems():
|
|
if info.get("check_uptake"):
|
|
product_template = info["product-name"]
|
|
for prev_version in prev_versions:
|
|
subs = {
|
|
"version": version,
|
|
"prev_version": prev_version
|
|
}
|
|
related_product = product_template % subs
|
|
|
|
enUS_platforms = set(self.config["platforms"])
|
|
paths_platforms = set(info["paths"].keys())
|
|
platforms = enUS_platforms.intersection(paths_platforms)
|
|
|
|
for platform in platforms:
|
|
bouncer_platform = info["paths"].get(platform).get('bouncer-platform')
|
|
dl.append(self._get_product_uptake(tuxedo_server_url, auth,
|
|
related_product, bouncer_platform))
|
|
return min(dl)
|
|
|
|
def monitor_uptake(self):
|
|
credentials_file = os.path.join(os.getcwd(),
|
|
self.config["credentials_file"])
|
|
credentials = {}
|
|
execfile(credentials_file, credentials)
|
|
auth = (credentials['tuxedoUsername'], credentials['tuxedoPassword'])
|
|
self.info("Starting the loop to determine the uptake monitoring ...")
|
|
|
|
start_time = datetime.datetime.now()
|
|
while True:
|
|
delta = (datetime.datetime.now() - start_time).seconds
|
|
if delta > self.config["poll_timeout"]:
|
|
self.error("Uptake monitoring sadly timed-out")
|
|
raise Exception("Time-out during uptake monitoring")
|
|
|
|
uptake = self._get_release_uptake(auth)
|
|
self.info("Current uptake value to check is {}".format(uptake))
|
|
|
|
if uptake >= self.config["min_uptake"]:
|
|
self.info("Uptake monitoring is complete!")
|
|
break
|
|
else:
|
|
self.info("Mirrors not yet updated, sleeping for a bit ...")
|
|
time.sleep(self.config["poll_interval"])
|
|
|
|
|
|
if __name__ == '__main__':
|
|
myScript = UptakeMonitoring()
|
|
myScript.run_and_exit()
|