blob: 3a89daf36f6ef68719733b8497462c198a9ae454 [file] [log] [blame]
Alex Klein146d4772019-06-20 13:48:25 -06001# Copyright 2019 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
Alex Kleine0fa6422019-06-21 12:01:39 -06005"""Router class for the Build API.
6
7Handles routing requests to the appropriate controller and handles service
8registration.
9"""
Alex Klein146d4772019-06-20 13:48:25 -060010
Alex Klein92341cd2020-02-27 14:11:04 -070011import collections
Alex Klein146d4772019-06-20 13:48:25 -060012import importlib
Chris McDonald1672ddb2021-07-21 11:48:23 -060013import logging
Alex Klein146d4772019-06-20 13:48:25 -060014import os
Tomasz Tylendab4292302021-08-08 18:59:36 +090015from types import ModuleType
16from typing import Callable, List, TYPE_CHECKING
Alex Klein146d4772019-06-20 13:48:25 -060017
Mike Frysinger2c024062021-05-22 15:43:22 -040018from chromite.third_party.google.protobuf import symbol_database
Alex Klein146d4772019-06-20 13:48:25 -060019
20from chromite.api import controller
21from chromite.api import field_handler
Alex Klein4de25e82019-08-05 15:58:39 -060022from chromite.api.gen.chromite.api import android_pb2
Alex Klein54e38e32019-06-21 14:54:17 -060023from chromite.api.gen.chromite.api import api_pb2
Alex Klein146d4772019-06-20 13:48:25 -060024from chromite.api.gen.chromite.api import artifacts_pb2
25from chromite.api.gen.chromite.api import binhost_pb2
26from chromite.api.gen.chromite.api import build_api_pb2
27from chromite.api.gen.chromite.api import depgraph_pb2
Jett Rink17ed0f52020-09-25 17:14:31 -060028from chromite.api.gen.chromite.api import firmware_pb2
Alex Klein146d4772019-06-20 13:48:25 -060029from chromite.api.gen.chromite.api import image_pb2
Alex Kleind4d9caa2021-11-10 15:44:52 -070030from chromite.api.gen.chromite.api import metadata_pb2
Alex Kleineb77ffa2019-05-28 14:47:44 -060031from chromite.api.gen.chromite.api import packages_pb2
George Engelbrechtfe63c8c2019-08-31 22:51:29 -060032from chromite.api.gen.chromite.api import payload_pb2
Alex Klein146d4772019-06-20 13:48:25 -060033from chromite.api.gen.chromite.api import sdk_pb2
34from chromite.api.gen.chromite.api import sysroot_pb2
35from chromite.api.gen.chromite.api import test_pb2
Tiancong Wangaf050172019-07-10 11:52:03 -070036from chromite.api.gen.chromite.api import toolchain_pb2
Alex Klein146d4772019-06-20 13:48:25 -060037from chromite.lib import cros_build_lib
Alex Klein146d4772019-06-20 13:48:25 -060038from chromite.lib import osutils
Alex Klein92341cd2020-02-27 14:11:04 -070039from chromite.utils import memoize
Alex Klein146d4772019-06-20 13:48:25 -060040
Mike Frysinger1cc8f1f2022-04-28 22:40:40 -040041
Tomasz Tylendab4292302021-08-08 18:59:36 +090042if TYPE_CHECKING:
Mike Frysinger1cc8f1f2022-04-28 22:40:40 -040043 from chromite.third_party import google
44
Tomasz Tylendab4292302021-08-08 18:59:36 +090045 from chromite.api import api_config
46 from chromite.api import message_util
Mike Frysinger88770ef2021-05-21 11:04:00 -040047
Alex Klein92341cd2020-02-27 14:11:04 -070048MethodData = collections.namedtuple(
49 'MethodData', ('service_descriptor', 'module_name', 'method_descriptor'))
Alex Klein146d4772019-06-20 13:48:25 -060050
Mike Frysingeref94e4c2020-02-10 23:59:54 -050051
Alex Klein146d4772019-06-20 13:48:25 -060052class Error(Exception):
53 """Base error class for the module."""
54
55
Alex Kleind3394c22020-06-16 14:05:06 -060056class InvalidSdkError(Error):
57 """Raised when the SDK is invalid or does not exist."""
58
59
Alex Klein146d4772019-06-20 13:48:25 -060060class CrosSdkNotRunError(Error):
61 """Raised when the cros_sdk command could not be run to enter the chroot."""
62
63
64# API Service Errors.
65class UnknownServiceError(Error):
66 """Error raised when the requested service has not been registered."""
67
68
69class ControllerModuleNotDefinedError(Error):
Alex Klein92341cd2020-02-27 14:11:04 -070070 """Error class for when no controller has been defined for a service."""
Alex Klein146d4772019-06-20 13:48:25 -060071
72
73class ServiceControllerNotFoundError(Error):
74 """Error raised when the service's controller cannot be imported."""
75
76
77# API Method Errors.
78class UnknownMethodError(Error):
Alex Klein92341cd2020-02-27 14:11:04 -070079 """The service has been defined in the proto, but the method has not."""
Alex Klein146d4772019-06-20 13:48:25 -060080
81
82class MethodNotFoundError(Error):
83 """The method's implementation cannot be found in the service's controller."""
84
85
86class Router(object):
87 """Encapsulates the request dispatching logic."""
88
Alex Kleine191ed62020-02-27 15:59:55 -070089 REEXEC_INPUT_FILE = 'input_proto'
90 REEXEC_OUTPUT_FILE = 'output_proto'
91 REEXEC_CONFIG_FILE = 'config_proto'
Alex Kleinbd6edf82019-07-18 10:30:49 -060092
Alex Klein146d4772019-06-20 13:48:25 -060093 def __init__(self):
94 self._services = {}
95 self._aliases = {}
96 # All imported generated messages get added to this symbol db.
97 self._sym_db = symbol_database.Default()
98
Alex Klein92341cd2020-02-27 14:11:04 -070099 # Save the service and method extension info for looking up
100 # configured extension data.
Alex Klein146d4772019-06-20 13:48:25 -0600101 extensions = build_api_pb2.DESCRIPTOR.extensions_by_name
Alex Klein92341cd2020-02-27 14:11:04 -0700102 self._svc_options_ext = extensions['service_options']
103 self._method_options_ext = extensions['method_options']
104
105 @memoize.Memoize
106 def _get_method_data(self, service_name, method_name):
107 """Get the descriptors and module name for the given Service/Method."""
108 try:
109 svc, module_name = self._services[service_name]
110 except KeyError:
111 raise UnknownServiceError(
112 'The %s service has not been registered.' % service_name)
113
114 try:
115 method_desc = svc.methods_by_name[method_name]
116 except KeyError:
117 raise UnknownMethodError('The %s method has not been defined in the %s '
118 'service.' % (method_name, service_name))
119
120 return MethodData(
121 service_descriptor=svc,
122 module_name=module_name,
123 method_descriptor=method_desc)
124
125 def _get_input_message_instance(self, service_name, method_name):
126 """Get an empty input message instance for the specified method."""
127 method_data = self._get_method_data(service_name, method_name)
128 return self._sym_db.GetPrototype(method_data.method_descriptor.input_type)()
129
130 def _get_output_message_instance(self, service_name, method_name):
131 """Get an empty output message instance for the specified method."""
132 method_data = self._get_method_data(service_name, method_name)
133 return self._sym_db.GetPrototype(
134 method_data.method_descriptor.output_type)()
135
136 def _get_module_name(self, service_name, method_name):
137 """Get the name of the module containing the endpoint implementation."""
138 return self._get_method_data(service_name, method_name).module_name
139
140 def _get_service_options(self, service_name, method_name):
141 """Get the configured service options for the endpoint."""
142 method_data = self._get_method_data(service_name, method_name)
143 svc_extensions = method_data.service_descriptor.GetOptions().Extensions
144 return svc_extensions[self._svc_options_ext]
145
146 def _get_method_options(self, service_name, method_name):
147 """Get the configured method options for the endpoint."""
148 method_data = self._get_method_data(service_name, method_name)
149 method_extensions = method_data.method_descriptor.GetOptions().Extensions
150 return method_extensions[self._method_options_ext]
Alex Klein146d4772019-06-20 13:48:25 -0600151
Tomasz Tylendab4292302021-08-08 18:59:36 +0900152 def Register(self, proto_module: ModuleType):
Alex Klein146d4772019-06-20 13:48:25 -0600153 """Register the services from a generated proto module.
154
155 Args:
Tomasz Tylendab4292302021-08-08 18:59:36 +0900156 proto_module: The generated proto module to register.
Alex Klein146d4772019-06-20 13:48:25 -0600157
158 Raises:
159 ServiceModuleNotDefinedError when the service cannot be found in the
160 provided module.
161 """
162 services = proto_module.DESCRIPTOR.services_by_name
163 for service_name, svc in services.items():
Alex Klein92341cd2020-02-27 14:11:04 -0700164 module_name = svc.GetOptions().Extensions[self._svc_options_ext].module
Alex Klein146d4772019-06-20 13:48:25 -0600165
166 if not module_name:
167 raise ControllerModuleNotDefinedError(
168 'The module must be defined in the service definition: %s.%s' %
169 (proto_module, service_name))
170
171 self._services[svc.full_name] = (svc, module_name)
172
173 def ListMethods(self):
174 """List all methods registered with the router."""
175 services = []
176 for service_name, (svc, _module) in self._services.items():
Alex Klein6cce6f62021-03-02 14:24:05 -0700177 svc_visibility = getattr(
178 svc.GetOptions().Extensions[self._svc_options_ext],
179 'service_visibility', build_api_pb2.LV_VISIBLE)
180 if svc_visibility == build_api_pb2.LV_HIDDEN:
181 continue
182
Alex Klein146d4772019-06-20 13:48:25 -0600183 for method_name in svc.methods_by_name.keys():
Alex Klein6cce6f62021-03-02 14:24:05 -0700184 method_options = self._get_method_options(service_name, method_name)
185 method_visibility = getattr(method_options, 'method_visibility',
186 build_api_pb2.LV_VISIBLE)
187 if method_visibility == build_api_pb2.LV_HIDDEN:
188 continue
189
Alex Klein146d4772019-06-20 13:48:25 -0600190 services.append('%s/%s' % (service_name, method_name))
191
192 return sorted(services)
193
Tomasz Tylendab4292302021-08-08 18:59:36 +0900194 def Route(self, service_name: str, method_name: str,
195 config: 'api_config.ApiConfig',
196 input_handler: 'message_util.MessageHandler',
197 output_handlers: List['message_util.MessageHandler'],
198 config_handler: 'message_util.MessageHandler') -> int:
Alex Klein146d4772019-06-20 13:48:25 -0600199 """Dispatch the request.
200
201 Args:
Tomasz Tylendab4292302021-08-08 18:59:36 +0900202 service_name: The fully qualified service name.
203 method_name: The name of the method being called.
204 config: The call configs.
205 input_handler: The request message handler.
206 output_handlers: The response message handlers.
207 config_handler: The config message handler.
Alex Klein146d4772019-06-20 13:48:25 -0600208
209 Returns:
Tomasz Tylendab4292302021-08-08 18:59:36 +0900210 The return code.
Alex Klein146d4772019-06-20 13:48:25 -0600211
212 Raises:
213 InvalidInputFileError when the input file cannot be read.
214 InvalidOutputFileError when the output file cannot be written.
215 ServiceModuleNotFoundError when the service module cannot be imported.
216 MethodNotFoundError when the method cannot be retrieved from the module.
217 """
Alex Klein92341cd2020-02-27 14:11:04 -0700218 input_msg = self._get_input_message_instance(service_name, method_name)
Alex Kleine191ed62020-02-27 15:59:55 -0700219 input_handler.read_into(input_msg)
Alex Klein146d4772019-06-20 13:48:25 -0600220
221 # Get an empty output message instance.
Alex Klein92341cd2020-02-27 14:11:04 -0700222 output_msg = self._get_output_message_instance(service_name, method_name)
Alex Klein146d4772019-06-20 13:48:25 -0600223
Alex Kleinbd6edf82019-07-18 10:30:49 -0600224 # Fetch the method options for chroot and method name overrides.
Alex Klein92341cd2020-02-27 14:11:04 -0700225 method_options = self._get_method_options(service_name, method_name)
Alex Klein146d4772019-06-20 13:48:25 -0600226
227 # Check the chroot settings before running.
Alex Klein92341cd2020-02-27 14:11:04 -0700228 service_options = self._get_service_options(service_name, method_name)
Alex Kleind1e9e5c2020-12-14 12:32:32 -0700229 if self._ChrootCheck(service_options, method_options, config):
Alex Klein146d4772019-06-20 13:48:25 -0600230 # Run inside the chroot instead.
231 logging.info('Re-executing the endpoint inside the chroot.')
Alex Kleine191ed62020-02-27 15:59:55 -0700232 return self._ReexecuteInside(input_msg, output_msg, config, input_handler,
233 output_handlers, config_handler,
234 service_name, method_name)
Alex Kleinbd6edf82019-07-18 10:30:49 -0600235
236 # Allow proto-based method name override.
237 if method_options.HasField('implementation_name'):
Alex Klein92341cd2020-02-27 14:11:04 -0700238 implementation_name = method_options.implementation_name
239 else:
240 implementation_name = method_name
Alex Klein146d4772019-06-20 13:48:25 -0600241
242 # Import the module and get the method.
Alex Klein92341cd2020-02-27 14:11:04 -0700243 module_name = self._get_module_name(service_name, method_name)
244 method_impl = self._GetMethod(module_name, implementation_name)
Alex Klein146d4772019-06-20 13:48:25 -0600245
246 # Successfully located; call and return.
Alex Klein69339cc2019-07-22 14:08:35 -0600247 return_code = method_impl(input_msg, output_msg, config)
Alex Klein146d4772019-06-20 13:48:25 -0600248 if return_code is None:
249 return_code = controller.RETURN_CODE_SUCCESS
250
Alex Kleine191ed62020-02-27 15:59:55 -0700251 for h in output_handlers:
252 h.write_from(output_msg)
Alex Klein146d4772019-06-20 13:48:25 -0600253
254 return return_code
255
Tomasz Tylendab4292302021-08-08 18:59:36 +0900256 def _ChrootCheck(self, service_options: 'google.protobuf.Message',
257 method_options: 'google.protobuf.Message',
258 config: 'api_config.ApiConfig') -> bool:
Alex Klein146d4772019-06-20 13:48:25 -0600259 """Check the chroot options, and execute assertion or note reexec as needed.
260
261 Args:
Tomasz Tylendab4292302021-08-08 18:59:36 +0900262 service_options: The service options.
263 method_options: The method options.
Alex Kleind1e9e5c2020-12-14 12:32:32 -0700264 config: The Build API call config instance.
Alex Klein146d4772019-06-20 13:48:25 -0600265
266 Returns:
Tomasz Tylendab4292302021-08-08 18:59:36 +0900267 True iff it needs to be reexeced inside the chroot.
Alex Klein146d4772019-06-20 13:48:25 -0600268
269 Raises:
270 cros_build_lib.DieSystemExit when the chroot setting cannot be satisfied.
271 """
Alex Kleind1e9e5c2020-12-14 12:32:32 -0700272 if not config.run_endpoint:
273 # Do not enter the chroot for validate only and mock calls.
274 return False
275
Alex Klein146d4772019-06-20 13:48:25 -0600276 chroot_assert = build_api_pb2.NO_ASSERTION
277 if method_options.HasField('method_chroot_assert'):
278 # Prefer the method option when set.
279 chroot_assert = method_options.method_chroot_assert
280 elif service_options.HasField('service_chroot_assert'):
281 # Fall back to the service option.
282 chroot_assert = service_options.service_chroot_assert
283
284 if chroot_assert == build_api_pb2.INSIDE:
285 return not cros_build_lib.IsInsideChroot()
286 elif chroot_assert == build_api_pb2.OUTSIDE:
287 # If it must be run outside we have to already be outside.
288 cros_build_lib.AssertOutsideChroot()
289
290 return False
291
Tomasz Tylendab4292302021-08-08 18:59:36 +0900292 def _ReexecuteInside(self, input_msg: 'google.protobuf.Message',
293 output_msg: 'google.protobuf.Message',
294 config: 'api_config.ApiConfig',
295 input_handler: 'message_util.MessageHandler',
296 output_handlers: List['message_util.MessageHandler'],
297 config_handler: 'message_util.MessageHandler',
298 service_name: str,
299 method_name: str):
Alex Klein146d4772019-06-20 13:48:25 -0600300 """Re-execute the service inside the chroot.
301
302 Args:
Tomasz Tylendab4292302021-08-08 18:59:36 +0900303 input_msg: The parsed input message.
304 output_msg: The empty output message instance.
305 config: The call configs.
306 input_handler: Input message handler.
307 output_handlers: Output message handlers.
308 config_handler: Config message handler.
309 service_name: The name of the service to run.
310 method_name: The name of the method to run.
Alex Klein146d4772019-06-20 13:48:25 -0600311 """
Alex Kleinc7d647f2020-01-06 12:00:48 -0700312 # Parse the chroot and clear the chroot field in the input message.
313 chroot = field_handler.handle_chroot(input_msg)
Alex Klein915cce92019-12-17 14:19:50 -0700314
Alex Kleind3394c22020-06-16 14:05:06 -0600315 if not chroot.exists():
316 raise InvalidSdkError('Chroot does not exist.')
317
Alex Kleinc7d647f2020-01-06 12:00:48 -0700318 # Use a ContextManagerStack to avoid the deep nesting this many
319 # context managers introduces.
320 with cros_build_lib.ContextManagerStack() as stack:
321 # TempDirs setup.
322 tempdir = stack.Add(chroot.tempdir).tempdir
323 sync_tempdir = stack.Add(chroot.tempdir).tempdir
324 # The copy-paths-in context manager to handle Path messages.
Alex Klein92341cd2020-02-27 14:11:04 -0700325 stack.Add(
326 field_handler.copy_paths_in,
327 input_msg,
328 chroot.tmp,
329 prefix=chroot.path)
Alex Kleinc7d647f2020-01-06 12:00:48 -0700330 # The sync-directories context manager to handle SyncedDir messages.
Alex Klein92341cd2020-02-27 14:11:04 -0700331 stack.Add(
332 field_handler.sync_dirs, input_msg, sync_tempdir, prefix=chroot.path)
Alex Klein146d4772019-06-20 13:48:25 -0600333
Alex Klein4089a492020-06-30 10:59:36 -0600334 # Parse goma.
Alex Kleinc7d647f2020-01-06 12:00:48 -0700335 chroot.goma = field_handler.handle_goma(input_msg, chroot.path)
Alex Klein9b7331e2019-12-30 14:37:21 -0700336
Joanna Wang92cad812021-11-03 14:52:08 -0700337 # Parse remoteexec.
338 chroot.remoteexec = field_handler.handle_remoteexec(input_msg)
339
Alex Klein4089a492020-06-30 10:59:36 -0600340 # Build inside-chroot paths for the input, output, and config messages.
Alex Kleinc7d647f2020-01-06 12:00:48 -0700341 new_input = os.path.join(tempdir, self.REEXEC_INPUT_FILE)
342 chroot_input = '/%s' % os.path.relpath(new_input, chroot.path)
343 new_output = os.path.join(tempdir, self.REEXEC_OUTPUT_FILE)
344 chroot_output = '/%s' % os.path.relpath(new_output, chroot.path)
Alex Kleind815ca62020-01-10 12:21:30 -0700345 new_config = os.path.join(tempdir, self.REEXEC_CONFIG_FILE)
346 chroot_config = '/%s' % os.path.relpath(new_config, chroot.path)
Alex Klein9b7331e2019-12-30 14:37:21 -0700347
Alex Klein4089a492020-06-30 10:59:36 -0600348 # Setup the inside-chroot message files.
Alex Kleinc7d647f2020-01-06 12:00:48 -0700349 logging.info('Writing input message to: %s', new_input)
Alex Kleine191ed62020-02-27 15:59:55 -0700350 input_handler.write_from(input_msg, path=new_input)
Alex Kleinc7d647f2020-01-06 12:00:48 -0700351 osutils.Touch(new_output)
Alex Kleind815ca62020-01-10 12:21:30 -0700352 logging.info('Writing config message to: %s', new_config)
Alex Kleine191ed62020-02-27 15:59:55 -0700353 config_handler.write_from(config.get_proto(), path=new_config)
Alex Klein146d4772019-06-20 13:48:25 -0600354
Alex Kleine191ed62020-02-27 15:59:55 -0700355 # We can use a single output to write the rest of them. Use the
356 # first one as the reexec output and just translate its output in
357 # the rest of the handlers after.
358 output_handler = output_handlers[0]
359
360 cmd = [
361 'build_api',
362 '%s/%s' % (service_name, method_name),
363 input_handler.input_arg,
364 chroot_input,
365 output_handler.output_arg,
366 chroot_output,
367 config_handler.config_arg,
368 chroot_config,
Alex Klein0b9edda2020-05-20 10:35:01 -0600369 '--debug',
Alex Kleine191ed62020-02-27 15:59:55 -0700370 ]
Alex Klein146d4772019-06-20 13:48:25 -0600371
Alex Kleinc7d647f2020-01-06 12:00:48 -0700372 try:
373 result = cros_build_lib.run(
374 cmd,
375 enter_chroot=True,
376 chroot_args=chroot.get_enter_args(),
377 check=False,
378 extra_env=chroot.env)
379 except cros_build_lib.RunCommandError:
380 # A non-zero return code will not result in an error, but one
381 # is still thrown when the command cannot be run in the first
382 # place. This is known to happen at least when the PATH does
383 # not include the chromite bin dir.
384 raise CrosSdkNotRunError('Unable to enter the chroot.')
Alex Klein69339cc2019-07-22 14:08:35 -0600385
Alex Kleinc7d647f2020-01-06 12:00:48 -0700386 logging.info('Endpoint execution completed, return code: %d',
387 result.returncode)
Alex Klein146d4772019-06-20 13:48:25 -0600388
Alex Kleinc7d647f2020-01-06 12:00:48 -0700389 # Transfer result files out of the chroot.
Alex Kleine191ed62020-02-27 15:59:55 -0700390 output_handler.read_into(output_msg, path=new_output)
391 field_handler.extract_results(input_msg, output_msg, chroot)
Alex Klein146d4772019-06-20 13:48:25 -0600392
Alex Kleine191ed62020-02-27 15:59:55 -0700393 # Write out all of the response formats.
394 for handler in output_handlers:
395 handler.write_from(output_msg)
Alex Kleinbd6edf82019-07-18 10:30:49 -0600396
Alex Kleinc7d647f2020-01-06 12:00:48 -0700397 return result.returncode
Alex Klein146d4772019-06-20 13:48:25 -0600398
Tomasz Tylendab4292302021-08-08 18:59:36 +0900399 def _GetMethod(self, module_name: str, method_name: str) -> Callable:
Alex Klein146d4772019-06-20 13:48:25 -0600400 """Get the implementation of the method for the service module.
401
402 Args:
Tomasz Tylendab4292302021-08-08 18:59:36 +0900403 module_name: The name of the service module.
404 method_name: The name of the method.
Alex Klein146d4772019-06-20 13:48:25 -0600405
406 Returns:
Tomasz Tylendab4292302021-08-08 18:59:36 +0900407 The method.
Alex Klein146d4772019-06-20 13:48:25 -0600408
409 Raises:
410 MethodNotFoundError when the method cannot be found in the module.
411 ServiceModuleNotFoundError when the service module cannot be imported.
412 """
413 try:
414 module = importlib.import_module(controller.IMPORT_PATTERN % module_name)
415 except ImportError as e:
Mike Frysinger6b5c3cd2019-08-27 16:51:00 -0400416 raise ServiceControllerNotFoundError(str(e))
Alex Klein146d4772019-06-20 13:48:25 -0600417 try:
418 return getattr(module, method_name)
419 except AttributeError as e:
Mike Frysinger6b5c3cd2019-08-27 16:51:00 -0400420 raise MethodNotFoundError(str(e))
Alex Klein146d4772019-06-20 13:48:25 -0600421
422
Tomasz Tylendab4292302021-08-08 18:59:36 +0900423def RegisterServices(router: Router):
Alex Klein146d4772019-06-20 13:48:25 -0600424 """Register all the services.
425
426 Args:
Tomasz Tylendab4292302021-08-08 18:59:36 +0900427 router: The router.
Alex Klein146d4772019-06-20 13:48:25 -0600428 """
Alex Klein4de25e82019-08-05 15:58:39 -0600429 router.Register(android_pb2)
Alex Klein54e38e32019-06-21 14:54:17 -0600430 router.Register(api_pb2)
Alex Klein146d4772019-06-20 13:48:25 -0600431 router.Register(artifacts_pb2)
432 router.Register(binhost_pb2)
433 router.Register(depgraph_pb2)
Jett Rink17ed0f52020-09-25 17:14:31 -0600434 router.Register(firmware_pb2)
Alex Klein146d4772019-06-20 13:48:25 -0600435 router.Register(image_pb2)
Alex Kleind4d9caa2021-11-10 15:44:52 -0700436 router.Register(metadata_pb2)
Alex Kleineb77ffa2019-05-28 14:47:44 -0600437 router.Register(packages_pb2)
George Engelbrechtfe63c8c2019-08-31 22:51:29 -0600438 router.Register(payload_pb2)
Alex Klein146d4772019-06-20 13:48:25 -0600439 router.Register(sdk_pb2)
440 router.Register(sysroot_pb2)
441 router.Register(test_pb2)
Tiancong Wangaf050172019-07-10 11:52:03 -0700442 router.Register(toolchain_pb2)
Alex Klein146d4772019-06-20 13:48:25 -0600443 logging.debug('Services registered successfully.')
444
445
446def GetRouter():
447 """Get a router that has had all of the services registered."""
448 router = Router()
449 RegisterServices(router)
450
451 return router