Justin Suen | f9095ee | 2021-06-25 18:25:44 +0000 | [diff] [blame] | 1 | #!/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 Suen | 0d7a909 | 2021-09-07 17:41:38 +0000 | [diff] [blame] | 7 | """Marshal various scheduling configs. Store them into the UFS datastore |
Justin Suen | 84529bd | 2021-07-22 18:06:48 +0000 | [diff] [blame] | 8 | through the Google datastore API. |
Justin Suen | f9095ee | 2021-06-25 18:25:44 +0000 | [diff] [blame] | 9 | |
Justin Suen | 84529bd | 2021-07-22 18:06:48 +0000 | [diff] [blame] | 10 | By default, this script converts a few config-related protos into datastore |
| 11 | entities: |
| 12 | |
| 13 | 1. ConfigBundleList from 'hw_design/generated/configs.jsonproto' |
Justin Suen | ca8e640 | 2021-09-15 22:38:11 +0000 | [diff] [blame^] | 14 | 2. DutAttributeList from |
| 15 | '.../chromiumos/src/config/generated/dut_attributes.jsonproto' |
Justin Suen | 5aaa7cd | 2021-09-01 08:55:53 +0000 | [diff] [blame] | 16 | 3. FlatConfigList from 'hw_design/generated/flattened.jsonproto' |
Justin Suen | 0d7a909 | 2021-09-07 17:41:38 +0000 | [diff] [blame] | 17 | 4. DeviceStabilityList from |
| 18 | '.../chromiumos/infra/config/testingconfig/generated/device_stability.cfg' |
Justin Suen | 84529bd | 2021-07-22 18:06:48 +0000 | [diff] [blame] | 19 | |
| 20 | The lists are parsed and individual entities are extracted. Using the datastore |
| 21 | client specified, it encodes the protos as datastore entities and stores them |
| 22 | into the UFS datastore. |
Justin Suen | f9095ee | 2021-06-25 18:25:44 +0000 | [diff] [blame] | 23 | """ |
| 24 | |
| 25 | import argparse |
| 26 | import datetime |
| 27 | import logging |
Justin Suen | 0d7a909 | 2021-09-07 17:41:38 +0000 | [diff] [blame] | 28 | import os |
Justin Suen | f9095ee | 2021-06-25 18:25:44 +0000 | [diff] [blame] | 29 | |
| 30 | from google.cloud import datastore |
| 31 | |
| 32 | from checker import io_utils |
| 33 | from common import proto_utils |
| 34 | |
| 35 | # type constants |
Justin Suen | 84529bd | 2021-07-22 18:06:48 +0000 | [diff] [blame] | 36 | CB_INPUT_TYPE = 'chromiumos.config.payload.ConfigBundleList' |
| 37 | CB_OUTPUT_TYPE = 'chromiumos.config.payload.ConfigBundle' |
| 38 | DA_INPUT_TYPE = 'chromiumos.test.api.DutAttributeList' |
| 39 | DA_OUTPUT_TYPE = 'chromiumos.test.api.DutAttribute' |
Justin Suen | 5aaa7cd | 2021-09-01 08:55:53 +0000 | [diff] [blame] | 40 | FC_INPUT_TYPE = 'chromiumos.config.payload.FlatConfigList' |
| 41 | FC_OUTPUT_TYPE = 'chromiumos.config.payload.FlatConfig' |
Justin Suen | 0d7a909 | 2021-09-07 17:41:38 +0000 | [diff] [blame] | 42 | DEV_STAB_INPUT_TYPE = 'chromiumos.test.dut.DeviceStabilityList' |
| 43 | DEV_STAB_OUTPUT_TYPE = 'chromiumos.test.dut.DeviceStability' |
Justin Suen | f9095ee | 2021-06-25 18:25:44 +0000 | [diff] [blame] | 44 | |
| 45 | # UFS services |
| 46 | UFS_DEV_PROJECT = 'unified-fleet-system-dev' |
| 47 | UFS_PROD_PROJECT = 'unified-fleet-system' |
| 48 | |
| 49 | # datastore constants |
| 50 | CONFIG_BUNDLE_KIND = 'ConfigBundle' |
Justin Suen | 84529bd | 2021-07-22 18:06:48 +0000 | [diff] [blame] | 51 | DUT_ATTRIBUTE_KIND = 'DutAttribute' |
Justin Suen | 5aaa7cd | 2021-09-01 08:55:53 +0000 | [diff] [blame] | 52 | FLAT_CONFIG_KIND = 'FlatConfig' |
Justin Suen | 0d7a909 | 2021-09-07 17:41:38 +0000 | [diff] [blame] | 53 | DEVICE_STABILITY_KIND = 'DeviceStability' |
Justin Suen | f9095ee | 2021-06-25 18:25:44 +0000 | [diff] [blame] | 54 | |
| 55 | |
| 56 | def 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 Suen | 5aaa7cd | 2021-09-01 08:55:53 +0000 | [diff] [blame] | 65 | def generate_config_bundle_id(bundle): |
Justin Suen | f9095ee | 2021-06-25 18:25:44 +0000 | [diff] [blame] | 66 | """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 Suen | 0d7a909 | 2021-09-07 17:41:38 +0000 | [diff] [blame] | 71 | def handle_config_bundle_list(cb_list_path, client): |
Justin Suen | 84529bd | 2021-07-22 18:06:48 +0000 | [diff] [blame] | 72 | """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 Suen | 0d7a909 | 2021-09-07 17:41:38 +0000 | [diff] [blame] | 79 | update_config(config_bundle, client, flat=False) |
Justin Suen | 84529bd | 2021-07-22 18:06:48 +0000 | [diff] [blame] | 80 | |
| 81 | |
Justin Suen | 5aaa7cd | 2021-09-01 08:55:53 +0000 | [diff] [blame] | 82 | def 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 Suen | 0d7a909 | 2021-09-07 17:41:38 +0000 | [diff] [blame] | 91 | def handle_flat_config_list(fc_list_path, client): |
Justin Suen | 5aaa7cd | 2021-09-01 08:55:53 +0000 | [diff] [blame] | 92 | """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 Suen | 0d7a909 | 2021-09-07 17:41:38 +0000 | [diff] [blame] | 99 | update_config(flat_config, client, flat=True) |
Justin Suen | 5aaa7cd | 2021-09-01 08:55:53 +0000 | [diff] [blame] | 100 | |
| 101 | |
Justin Suen | 0d7a909 | 2021-09-07 17:41:38 +0000 | [diff] [blame] | 102 | def update_config(config, client, flat=False): |
Justin Suen | 5aaa7cd | 2021-09-01 08:55:53 +0000 | [diff] [blame] | 103 | """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 Suen | f9095ee | 2021-06-25 18:25:44 +0000 | [diff] [blame] | 111 | |
Justin Suen | 5aaa7cd | 2021-09-01 08:55:53 +0000 | [diff] [blame] | 112 | key = client.key(kind, eid) |
Justin Suen | f9095ee | 2021-06-25 18:25:44 +0000 | [diff] [blame] | 113 | entity = datastore.Entity( |
| 114 | key=key, |
| 115 | exclude_from_indexes=['ConfigData'], |
| 116 | ) |
Justin Suen | 5aaa7cd | 2021-09-01 08:55:53 +0000 | [diff] [blame] | 117 | entity['ConfigData'] = config.SerializeToString() |
Justin Suen | f9095ee | 2021-06-25 18:25:44 +0000 | [diff] [blame] | 118 | entity['updated'] = datetime.datetime.now() |
| 119 | |
Justin Suen | 5aaa7cd | 2021-09-01 08:55:53 +0000 | [diff] [blame] | 120 | logging.info('update_config: putting entity into datastore for %s', eid) |
Justin Suen | 84529bd | 2021-07-22 18:06:48 +0000 | [diff] [blame] | 121 | client.put(entity) |
| 122 | |
| 123 | |
Justin Suen | 0d7a909 | 2021-09-07 17:41:38 +0000 | [diff] [blame] | 124 | def handle_dut_attribute_list(dut_attr_list_path, client): |
Justin Suen | 84529bd | 2021-07-22 18:06:48 +0000 | [diff] [blame] | 125 | """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 Suen | 0d7a909 | 2021-09-07 17:41:38 +0000 | [diff] [blame] | 132 | update_dut_attribute(dut_attribute, client) |
Justin Suen | 84529bd | 2021-07-22 18:06:48 +0000 | [diff] [blame] | 133 | |
| 134 | |
Justin Suen | 0d7a909 | 2021-09-07 17:41:38 +0000 | [diff] [blame] | 135 | def update_dut_attribute(attr, client): |
Justin Suen | 84529bd | 2021-07-22 18:06:48 +0000 | [diff] [blame] | 136 | """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 Suen | 84529bd | 2021-07-22 18:06:48 +0000 | [diff] [blame] | 140 | 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 Suen | f9095ee | 2021-06-25 18:25:44 +0000 | [diff] [blame] | 151 | |
| 152 | |
Justin Suen | 0d7a909 | 2021-09-07 17:41:38 +0000 | [diff] [blame] | 153 | def 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 | |
| 164 | def 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 Suen | f9095ee | 2021-06-25 18:25:44 +0000 | [diff] [blame] | 188 | if __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 Suen | f9095ee | 2021-06-25 18:25:44 +0000 | [diff] [blame] | 196 | '--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 Suen | f9095ee | 2021-06-25 18:25:44 +0000 | [diff] [blame] | 204 | options = parser.parse_args() |
Justin Suen | ca8e640 | 2021-09-15 22:38:11 +0000 | [diff] [blame^] | 205 | ufs_ds_client = datastore.Client( |
| 206 | project=get_ufs_project(options.env), |
| 207 | namespace="os", |
| 208 | ) |
Justin Suen | 0d7a909 | 2021-09-07 17:41:38 +0000 | [diff] [blame] | 209 | script_dir = os.path.dirname(os.path.realpath(__file__)) |
Justin Suen | f9095ee | 2021-06-25 18:25:44 +0000 | [diff] [blame] | 210 | |
Justin Suen | 84529bd | 2021-07-22 18:06:48 +0000 | [diff] [blame] | 211 | handle_config_bundle_list("hw_design/generated/configs.jsonproto", |
Justin Suen | 0d7a909 | 2021-09-07 17:41:38 +0000 | [diff] [blame] | 212 | ufs_ds_client) |
Sean McAllister | cf0db3a | 2021-09-14 17:03:47 -0600 | [diff] [blame] | 213 | 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 Suen | 5aaa7cd | 2021-09-01 08:55:53 +0000 | [diff] [blame] | 219 | handle_flat_config_list("hw_design/generated/flattened.jsonproto", |
Justin Suen | 0d7a909 | 2021-09-07 17:41:38 +0000 | [diff] [blame] | 220 | ufs_ds_client) |
| 221 | handle_device_stability_list( |
| 222 | os.path.realpath( |
| 223 | os.path.join( |
| 224 | script_dir, |
Justin Suen | 7c6674c | 2021-09-07 20:00:50 +0000 | [diff] [blame] | 225 | "../../../infra/config/testingconfig/generated/device_stability.cfg" |
Justin Suen | 0d7a909 | 2021-09-07 17:41:38 +0000 | [diff] [blame] | 226 | )), ufs_ds_client) |