blob: 30e9f02f55ac03085432a9d35dbd5422e39f785d [file] [log] [blame]
Justin Suenf9095ee2021-06-25 18:25:44 +00001#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3
4# Copyright 2021 The Chromium OS Authors. All rights reserved.
5# Use of this source code is governed by a BSD-style license that can be
6# found in the LICENSE file.
Justin Suen0d7a9092021-09-07 17:41:38 +00007"""Marshal various scheduling configs. Store them into the UFS datastore
Justin Suen84529bd2021-07-22 18:06:48 +00008through the Google datastore API.
Justin Suenf9095ee2021-06-25 18:25:44 +00009
Justin Suen84529bd2021-07-22 18:06:48 +000010By default, this script converts a few config-related protos into datastore
11entities:
12
131. ConfigBundleList from 'hw_design/generated/configs.jsonproto'
Justin Suenca8e6402021-09-15 22:38:11 +0000142. DutAttributeList from
15 '.../chromiumos/src/config/generated/dut_attributes.jsonproto'
Justin Suen5aaa7cd2021-09-01 08:55:53 +0000163. FlatConfigList from 'hw_design/generated/flattened.jsonproto'
Justin Suen0d7a9092021-09-07 17:41:38 +0000174. DeviceStabilityList from
18 '.../chromiumos/infra/config/testingconfig/generated/device_stability.cfg'
Justin Suen84529bd2021-07-22 18:06:48 +000019
20The lists are parsed and individual entities are extracted. Using the datastore
21client specified, it encodes the protos as datastore entities and stores them
22into the UFS datastore.
Justin Suenf9095ee2021-06-25 18:25:44 +000023"""
24
25import argparse
26import datetime
27import logging
Justin Suen0d7a9092021-09-07 17:41:38 +000028import os
Justin Suenf9095ee2021-06-25 18:25:44 +000029
30from google.cloud import datastore
31
32from checker import io_utils
33from common import proto_utils
34
35# type constants
Justin Suen84529bd2021-07-22 18:06:48 +000036CB_INPUT_TYPE = 'chromiumos.config.payload.ConfigBundleList'
37CB_OUTPUT_TYPE = 'chromiumos.config.payload.ConfigBundle'
38DA_INPUT_TYPE = 'chromiumos.test.api.DutAttributeList'
39DA_OUTPUT_TYPE = 'chromiumos.test.api.DutAttribute'
Justin Suen5aaa7cd2021-09-01 08:55:53 +000040FC_INPUT_TYPE = 'chromiumos.config.payload.FlatConfigList'
41FC_OUTPUT_TYPE = 'chromiumos.config.payload.FlatConfig'
Justin Suen0d7a9092021-09-07 17:41:38 +000042DEV_STAB_INPUT_TYPE = 'chromiumos.test.dut.DeviceStabilityList'
43DEV_STAB_OUTPUT_TYPE = 'chromiumos.test.dut.DeviceStability'
Justin Suenf9095ee2021-06-25 18:25:44 +000044
45# UFS services
46UFS_DEV_PROJECT = 'unified-fleet-system-dev'
47UFS_PROD_PROJECT = 'unified-fleet-system'
48
49# datastore constants
50CONFIG_BUNDLE_KIND = 'ConfigBundle'
Justin Suen84529bd2021-07-22 18:06:48 +000051DUT_ATTRIBUTE_KIND = 'DutAttribute'
Justin Suen5aaa7cd2021-09-01 08:55:53 +000052FLAT_CONFIG_KIND = 'FlatConfig'
Justin Suen0d7a9092021-09-07 17:41:38 +000053DEVICE_STABILITY_KIND = 'DeviceStability'
Justin Suenf9095ee2021-06-25 18:25:44 +000054
55
56def get_ufs_project(env):
57 """Return project name based on env argument."""
58 if env == 'dev':
59 return UFS_DEV_PROJECT
60 if env == 'prod':
61 return UFS_PROD_PROJECT
62 raise RuntimeError('get_ufs_project: environment %s not supported' % env)
63
64
Justin Suen5aaa7cd2021-09-01 08:55:53 +000065def generate_config_bundle_id(bundle):
Justin Suenf9095ee2021-06-25 18:25:44 +000066 """Generate ConfigBundleEntity id as ${program_id}-${design_id}."""
67 return bundle.design_list[0].program_id.value + '-' + bundle.design_list[
68 0].id.value
69
70
Justin Suen0d7a9092021-09-07 17:41:38 +000071def handle_config_bundle_list(cb_list_path, client):
Justin Suen84529bd2021-07-22 18:06:48 +000072 """Take a path to a ConfigBundleList, iterate through the list and store into
73 UFS datastore based on env.
74 """
75 cb_list = io_utils.read_json_proto(
76 protodb.GetSymbol(CB_INPUT_TYPE)(), cb_list_path)
77
78 for config_bundle in cb_list.values:
Justin Suen0d7a9092021-09-07 17:41:38 +000079 update_config(config_bundle, client, flat=False)
Justin Suen84529bd2021-07-22 18:06:48 +000080
81
Justin Suen5aaa7cd2021-09-01 08:55:53 +000082def generate_flat_config_id(bundle):
83 """Generate FlatConfigEntity id as ${program_id}-${design_id}-${design_config_id}
84 if design_config_id is available. Else ${program_id}-${design_id}."""
85 if bundle.hw_design_config.id.value:
86 return bundle.hw_design.program_id.value + '-' + bundle.hw_design.id.value \
87 + '-' + bundle.hw_design_config.id.value
88 return bundle.hw_design.program_id.value + '-' + bundle.hw_design.id.value
89
90
Justin Suen0d7a9092021-09-07 17:41:38 +000091def handle_flat_config_list(fc_list_path, client):
Justin Suen5aaa7cd2021-09-01 08:55:53 +000092 """Take a path to a FlatConfigList, iterate through the list and store into
93 UFS datastore based on env.
94 """
95 fc_list = io_utils.read_json_proto(
96 protodb.GetSymbol(FC_INPUT_TYPE)(), fc_list_path)
97
98 for flat_config in fc_list.values:
Justin Suen0d7a9092021-09-07 17:41:38 +000099 update_config(flat_config, client, flat=True)
Justin Suen5aaa7cd2021-09-01 08:55:53 +0000100
101
Justin Suen0d7a9092021-09-07 17:41:38 +0000102def update_config(config, client, flat=False):
Justin Suen5aaa7cd2021-09-01 08:55:53 +0000103 """Take a ConfigBundle or FlatConfig and store it an an entity in the UFS datastore."""
104 if flat:
105 kind = FLAT_CONFIG_KIND
106 eid = generate_flat_config_id(config)
107 else:
108 kind = CONFIG_BUNDLE_KIND
109 eid = generate_config_bundle_id(config)
110 logging.info('update_config: handling %s', eid)
Justin Suenf9095ee2021-06-25 18:25:44 +0000111
Justin Suen5aaa7cd2021-09-01 08:55:53 +0000112 key = client.key(kind, eid)
Justin Suenf9095ee2021-06-25 18:25:44 +0000113 entity = datastore.Entity(
114 key=key,
115 exclude_from_indexes=['ConfigData'],
116 )
Justin Suen5aaa7cd2021-09-01 08:55:53 +0000117 entity['ConfigData'] = config.SerializeToString()
Justin Suenf9095ee2021-06-25 18:25:44 +0000118 entity['updated'] = datetime.datetime.now()
119
Justin Suen5aaa7cd2021-09-01 08:55:53 +0000120 logging.info('update_config: putting entity into datastore for %s', eid)
Justin Suen84529bd2021-07-22 18:06:48 +0000121 client.put(entity)
122
123
Justin Suen0d7a9092021-09-07 17:41:38 +0000124def handle_dut_attribute_list(dut_attr_list_path, client):
Justin Suen84529bd2021-07-22 18:06:48 +0000125 """Take a path to a DutAttributeList, iterate through the list and store into
126 UFS datastore based on env.
127 """
128 dut_attr_list = io_utils.read_json_proto(
129 protodb.GetSymbol(DA_INPUT_TYPE)(), dut_attr_list_path)
130
131 for dut_attribute in dut_attr_list.dut_attributes:
Justin Suen0d7a9092021-09-07 17:41:38 +0000132 update_dut_attribute(dut_attribute, client)
Justin Suen84529bd2021-07-22 18:06:48 +0000133
134
Justin Suen0d7a9092021-09-07 17:41:38 +0000135def update_dut_attribute(attr, client):
Justin Suen84529bd2021-07-22 18:06:48 +0000136 """Take a DutAttribute and store it in the UFS datastore as a DutAttributeEntity."""
137 eid = attr.id.value
138 logging.info('update_dut_attribute: handling %s', eid)
139
Justin Suen84529bd2021-07-22 18:06:48 +0000140 key = client.key(DUT_ATTRIBUTE_KIND, eid)
141 entity = datastore.Entity(
142 key=key,
143 exclude_from_indexes=['AttributeData'],
144 )
145 entity['AttributeData'] = attr.SerializeToString()
146 entity['updated'] = datetime.datetime.now()
147
148 logging.info('update_dut_attribute: putting entity into datastore for %s',
149 eid)
150 client.put(entity)
Justin Suenf9095ee2021-06-25 18:25:44 +0000151
152
Justin Suen0d7a9092021-09-07 17:41:38 +0000153def handle_device_stability_list(dev_stab_list_path, client):
154 """Take a path to a DeviceStabilityList, iterate through the list and store
155 into UFS datastore based on env.
156 """
157 dev_stab_list = io_utils.read_json_proto(
158 protodb.GetSymbol(DEV_STAB_INPUT_TYPE)(), dev_stab_list_path)
159
160 for dev_stab in dev_stab_list.values:
161 update_device_stability(dev_stab, client)
162
163
164def update_device_stability(dev_stab, client):
165 """Take a DeviceStability and store it in the UFS datastore as a
166 DeviceStabilityEntity.
167 """
168 # TODO (justinsuen): May need to change this eventually. This assumes the use
169 # of a single model (DutAttribute ID design_id) when defining a
170 # DeviceStability entry.
171 # http://cs/chromeos_internal/infra/config/testingconfig/target_test_requirements_config_helper.star?l=155
172 for eid in dev_stab.dut_criteria[0].values:
173 logging.info('update_device_stability: handling %s', eid)
174
175 key = client.key(DEVICE_STABILITY_KIND, eid)
176 entity = datastore.Entity(
177 key=key,
178 exclude_from_indexes=['StabilityData'],
179 )
180 entity['StabilityData'] = dev_stab.SerializeToString()
181 entity['updated'] = datetime.datetime.now()
182
183 logging.info(
184 'update_device_stability: putting entity into datastore for %s', eid)
185 client.put(entity)
186
187
Justin Suenf9095ee2021-06-25 18:25:44 +0000188if __name__ == '__main__':
189 logging.basicConfig(level=logging.INFO)
190 parser = argparse.ArgumentParser(
191 description=__doc__,
192 formatter_class=argparse.RawDescriptionHelpFormatter,
193 )
194
195 parser.add_argument(
Justin Suenf9095ee2021-06-25 18:25:44 +0000196 '--env',
197 type=str,
198 default='dev',
199 help='environment flag for UFS service',
200 )
201
202 # load database of protobuffer name -> Type
203 protodb = proto_utils.create_symbol_db()
Justin Suenf9095ee2021-06-25 18:25:44 +0000204 options = parser.parse_args()
Justin Suenca8e6402021-09-15 22:38:11 +0000205 ufs_ds_client = datastore.Client(
206 project=get_ufs_project(options.env),
207 namespace="os",
208 )
Justin Suen0d7a9092021-09-07 17:41:38 +0000209 script_dir = os.path.dirname(os.path.realpath(__file__))
Justin Suenf9095ee2021-06-25 18:25:44 +0000210
Justin Suen84529bd2021-07-22 18:06:48 +0000211 handle_config_bundle_list("hw_design/generated/configs.jsonproto",
Justin Suen0d7a9092021-09-07 17:41:38 +0000212 ufs_ds_client)
Sean McAllistercf0db3a2021-09-14 17:03:47 -0600213 handle_dut_attribute_list(
214 os.path.realpath(
215 os.path.join(
216 script_dir,
217 "../generated/dut_attributes.jsonproto",
218 )), ufs_ds_client)
Justin Suen5aaa7cd2021-09-01 08:55:53 +0000219 handle_flat_config_list("hw_design/generated/flattened.jsonproto",
Justin Suen0d7a9092021-09-07 17:41:38 +0000220 ufs_ds_client)
221 handle_device_stability_list(
222 os.path.realpath(
223 os.path.join(
224 script_dir,
Justin Suen7c6674c2021-09-07 20:00:50 +0000225 "../../../infra/config/testingconfig/generated/device_stability.cfg"
Justin Suen0d7a9092021-09-07 17:41:38 +0000226 )), ufs_ds_client)