blob: 2ab46e7d93696c0fe7f613b4c7c54f5e0f96551b [file] [log] [blame]
# Copyright 2024 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Module for building and scheduling a CTPv2 Request."""
import json
import safe_log
import analytics
import buildbucket
import request_helper
from chromite.third_party.infra_libs.buildbucket.proto import common_pb2 as bb_common_pb2
from chromite.api.gen.chromiumos.test.api import ctp2_pb2 as ctpv2_request
from google.protobuf import json_format
class CTPv2Request(object):
"""ctpv2 request constructor and scheduler."""
def __init__(self, params):
self.params = params
self.req_tags = buildbucket._bb_tags(params['suite'])
self.req_tags.append(bb_common_pb2.StringPair(
key='build',
value=params['build'],
))
self.request = ctpv2_request.CTPv2Request()
self._form_ctpv2_request()
def schedule(self, platform_client, cred, builder):
"""Form the scheduling request and send to client.
Args:
platform_client: prpc client to build bucket.
cred: client credentials.
builder: A builder_common_pb2.BuilderID instance.
"""
req_json = '{ "ctpv2_request": %s }' % json_format.MessageToJson(self.request)
req_name = self.params['suite'] + '_' + self.params['build']
req_build = platform_client._build_request(req_json, self.req_tags, builder)
safe_log.debug('Raw request to buildbucket: %r', req_build)
resp = platform_client.client.ScheduleBuild(req_build,
credentials=cred,
timeout=buildbucket.PRPC_TIMEOUT_SEC)
safe_log.debug('Response from buildbucket: %r', resp)
if request_helper.key_not_none(self.params, 'task_id'):
execution_task = analytics.ExecutionTask(self.params['task_id'], req_name)
execution_task.update_result(resp)
try:
if not execution_task.upload():
safe_log.warning('Failed to insert row: %r', execution_task)
# For any exceptions from BQ, only log it.
except Exception as e: #pylint: disable=broad-except
safe_log.exception('Failed to insert row: %r, got error: %s', execution_task,
str(e))
def _form_ctpv2_request(self):
"""Entry point for creaing the ctpv2 request."""
self._form_ctpv2_targets()
self._form_ctpv2_suite_request()
if request_helper.key_not_none(self.params, 'pool'):
self.request.pool = self.params['pool']
if request_helper.key_not_none(self.params, 'karbon_filters'):
request_helper.form_ctpv2_filters(self.request.karbon_filters, json.loads(self.params['karbon_filters']))
if request_helper.key_not_none(self.params, 'koffee_filters'):
request_helper.form_ctpv2_filters(self.request.koffee_filters, json.loads(self.params['koffee_filters']))
def _form_ctpv2_suite_request(self):
"""Fills in the ctpv2 field for suite_request."""
suite_request = self.request.suite_request
suite_request.test_suite.name = self.params['suite']
include_tags = self.params.get('include_tags', None)
exclude_tags = self.params.get('exclude_tags', None)
include_names = self.params.get('inlcude_names', None)
exclude_names = self.params.get('exclude_names', None)
if include_tags or exclude_tags or include_names or exclude_names:
tag_criteria = suite_request.test_suite.test_case_tag_criteria
tag_criteria.tags.extend(buildbucket._get_test_tags(include_tags))
tag_criteria.tag_excludes.extend(buildbucket._get_test_tags(exclude_tags))
tag_criteria.test_names.extend(buildbucket._get_test_tags(include_names))
tag_criteria.test_name_excludes.extend(buildbucket._get_test_tags(exclude_names))
def _form_ctpv2_targets(self):
"""Parse out targets from params and create ctpv2 target objects.
Use targets field for individual dut requests. Use schedule targets
field for multi-dut requests.
"""
if not request_helper.key_not_none(self.params, 'targets'):
return
targets = self.request.targets
schedule_targets = self.request.schedule_targets
for dut_targets in json.loads(self.params['targets']):
if len(dut_targets) == 1:
target_dict = dut_targets[0]
target = targets.add()
self._form_ctpv2_target(target, target_dict)
else:
schedule_target = schedule_targets.add()
for dut_target in dut_targets:
target = schedule_target.targets.add()
self._form_ctpv2_target(target, dut_target)
def _form_ctpv2_target(self, target, target_dict):
"""Fill in target fields from dictionary of values.
Args:
target: target proto object being filled.
target_dict: dict containing target fields.
"""
sw_targets = target.sw_targets
sw_target = sw_targets.add()
if request_helper.key_not_none(target_dict, 'board'):
target.hw_target.legacy_hw.board = target_dict['board']
if request_helper.key_not_none(target_dict, 'model'):
target.hw_target.legacy_hw.model = target_dict['model']
if request_helper.key_not_none(target_dict, 'variant'):
sw_target.legacy_sw.variant = target_dict['variant']
if request_helper.key_not_none(target_dict, 'build_type'):
sw_target.legacy_sw.build = target_dict['build_type']
if request_helper.key_not_none(target_dict, 'test_source_build'):
sw_target.legacy_sw.gcs_path = buildbucket.get_gs_prefix(self.params) + target_dict['test_source_build']
self.req_tags.append(bb_common_pb2.StringPair(
key='label-image',
value=target_dict['test_source_build'],
))