Schema serving grpc API for introspective clients
diff --git a/voltha/core/protos/Makefile b/voltha/core/protos/Makefile
index dd5542b..b602c4d 100644
--- a/voltha/core/protos/Makefile
+++ b/voltha/core/protos/Makefile
@@ -42,7 +42,15 @@
%_pb2.py: %.proto Makefile
@echo "Building protocol buffer artifacts from $<"
- env LD_LIBRARY_PATH=$(PROTOC_LIBDIR) python -m grpc.tools.protoc -I. -I./third_party --python_out=. --grpc_python_out=. --descriptor_set_out=$(basename $<).desc --include_source_info $<
+ env LD_LIBRARY_PATH=$(PROTOC_LIBDIR) python -m grpc.tools.protoc \
+ -I. \
+ -I./third_party \
+ --python_out=. \
+ --grpc_python_out=. \
+ --descriptor_set_out=$(basename $<).desc \
+ --include_imports \
+ --include_source_info \
+ $<
clean:
rm -f $(PROTO_PB2_FILES) $(PROTO_DESC_FILES)
diff --git a/voltha/core/protos/third_party/google/api/annotations.desc b/voltha/core/protos/third_party/google/api/annotations.desc
index 67f970d..d159f06 100644
--- a/voltha/core/protos/third_party/google/api/annotations.desc
+++ b/voltha/core/protos/third_party/google/api/annotations.desc
Binary files differ
diff --git a/voltha/core/protos/voltha.desc b/voltha/core/protos/voltha.desc
index d22a73b..b1755ef 100644
--- a/voltha/core/protos/voltha.desc
+++ b/voltha/core/protos/voltha.desc
Binary files differ
diff --git a/voltha/core/protos/voltha.proto b/voltha/core/protos/voltha.proto
index 87b6dda..9ce135a 100644
--- a/voltha/core/protos/voltha.proto
+++ b/voltha/core/protos/voltha.proto
@@ -8,6 +8,17 @@
option java_outer_classname = "VolthaProtos";
option csharp_namespace = "Opencord.Voltha.Voltha";
+// Proto file and compiled descriptor for this interface
+message Schema {
+
+ // file name -> proto file content
+ map<string, string> protos = 1;
+
+ // file name -> gzip compressed protobuf of descriptor
+ map<string, bytes> descriptors = 2;
+
+}
+
// Empty message
message NullMessage {}
@@ -26,6 +37,17 @@
}
+// Schema services
+service SchemaService {
+
+ // Return active grpc schemas
+ rpc GetSchema(NullMessage) returns (Schema) {
+ option (google.api.http) = {
+ get: "/schema"
+ };
+ }
+}
+
// Health related services
service HealthService {
diff --git a/voltha/core/protos/voltha_pb2.py b/voltha/core/protos/voltha_pb2.py
index 176d023..e82df67 100644
--- a/voltha/core/protos/voltha_pb2.py
+++ b/voltha/core/protos/voltha_pb2.py
@@ -20,7 +20,7 @@
name='voltha.proto',
package='voltha',
syntax='proto3',
- serialized_pb=_b('\n\x0cvoltha.proto\x12\x06voltha\x1a\x1cgoogle/api/annotations.proto\"\r\n\x0bNullMessage\"v\n\x0cHealthStatus\x12/\n\x05state\x18\x01 \x01(\x0e\x32 .voltha.HealthStatus.HealthState\"5\n\x0bHealthState\x12\x0b\n\x07HEALTHY\x10\x00\x12\x0e\n\nOVERLOADED\x10\x01\x12\t\n\x05\x44YING\x10\x02\"q\n\x07\x41\x64\x64ress\x12\n\n\x02id\x18\x07 \x01(\t\x12\x0e\n\x06street\x18\x01 \x01(\t\x12\x0f\n\x07street2\x18\x02 \x01(\t\x12\x0f\n\x07street3\x18\x03 \x01(\t\x12\x0c\n\x04\x63ity\x18\x04 \x01(\t\x12\r\n\x05state\x18\x05 \x01(\t\x12\x0b\n\x03zip\x18\x06 \x01(\r\"/\n\tAddresses\x12\"\n\taddresses\x18\x01 \x03(\x0b\x32\x0f.voltha.Address\"\x9f\x01\n\x0bMoreComplex\x12$\n\x06health\x18\x01 \x01(\x0b\x32\x14.voltha.HealthStatus\x12\x13\n\x0b\x66oo_counter\x18\x02 \x01(\x05\x12\x0c\n\x04name\x18\x03 \x01(\t\x12%\n\x08\x63hildren\x18\x04 \x03(\x0b\x32\x13.voltha.MoreComplex\x12 \n\x07\x61\x64\x64ress\x18\x05 \x01(\x0b\x32\x0f.voltha.Address\"\x10\n\x02ID\x12\n\n\x02id\x18\x01 \x01(\t2a\n\rHealthService\x12P\n\x0fGetHealthStatus\x12\x13.voltha.NullMessage\x1a\x14.voltha.HealthStatus\"\x12\x82\xd3\xe4\x93\x02\x0c\x12\x07/health:\x01*2\xb6\x02\n\x0e\x45xampleService\x12K\n\rListAddresses\x12\x13.voltha.NullMessage\x1a\x11.voltha.Addresses\"\x12\x82\xd3\xe4\x93\x02\x0c\x12\n/addresses\x12\x42\n\nGetAddress\x12\n.voltha.ID\x1a\x0f.voltha.Address\"\x17\x82\xd3\xe4\x93\x02\x11\x12\x0f/addresses/{id}\x12H\n\rCreateAddress\x12\x0f.voltha.Address\x1a\x0f.voltha.Address\"\x15\x82\xd3\xe4\x93\x02\x0f\"\n/addresses:\x01*\x12I\n\rDeleteAddress\x12\n.voltha.ID\x1a\x13.voltha.NullMessage\"\x17\x82\xd3\xe4\x93\x02\x11*\x0f/addresses/{id}B<\n\x13org.opencord.volthaB\x0cVolthaProtos\xaa\x02\x16Opencord.Voltha.Volthab\x06proto3')
+ serialized_pb=_b('\n\x0cvoltha.proto\x12\x06voltha\x1a\x1cgoogle/api/annotations.proto\"\xcd\x01\n\x06Schema\x12*\n\x06protos\x18\x01 \x03(\x0b\x32\x1a.voltha.Schema.ProtosEntry\x12\x34\n\x0b\x64\x65scriptors\x18\x02 \x03(\x0b\x32\x1f.voltha.Schema.DescriptorsEntry\x1a-\n\x0bProtosEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x32\n\x10\x44\x65scriptorsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\"\r\n\x0bNullMessage\"v\n\x0cHealthStatus\x12/\n\x05state\x18\x01 \x01(\x0e\x32 .voltha.HealthStatus.HealthState\"5\n\x0bHealthState\x12\x0b\n\x07HEALTHY\x10\x00\x12\x0e\n\nOVERLOADED\x10\x01\x12\t\n\x05\x44YING\x10\x02\"q\n\x07\x41\x64\x64ress\x12\n\n\x02id\x18\x07 \x01(\t\x12\x0e\n\x06street\x18\x01 \x01(\t\x12\x0f\n\x07street2\x18\x02 \x01(\t\x12\x0f\n\x07street3\x18\x03 \x01(\t\x12\x0c\n\x04\x63ity\x18\x04 \x01(\t\x12\r\n\x05state\x18\x05 \x01(\t\x12\x0b\n\x03zip\x18\x06 \x01(\r\"/\n\tAddresses\x12\"\n\taddresses\x18\x01 \x03(\x0b\x32\x0f.voltha.Address\"\x9f\x01\n\x0bMoreComplex\x12$\n\x06health\x18\x01 \x01(\x0b\x32\x14.voltha.HealthStatus\x12\x13\n\x0b\x66oo_counter\x18\x02 \x01(\x05\x12\x0c\n\x04name\x18\x03 \x01(\t\x12%\n\x08\x63hildren\x18\x04 \x03(\x0b\x32\x13.voltha.MoreComplex\x12 \n\x07\x61\x64\x64ress\x18\x05 \x01(\x0b\x32\x0f.voltha.Address\"\x10\n\x02ID\x12\n\n\x02id\x18\x01 \x01(\t2R\n\rSchemaService\x12\x41\n\tGetSchema\x12\x13.voltha.NullMessage\x1a\x0e.voltha.Schema\"\x0f\x82\xd3\xe4\x93\x02\t\x12\x07/schema2^\n\rHealthService\x12M\n\x0fGetHealthStatus\x12\x13.voltha.NullMessage\x1a\x14.voltha.HealthStatus\"\x0f\x82\xd3\xe4\x93\x02\t\x12\x07/health2\xb6\x02\n\x0e\x45xampleService\x12K\n\rListAddresses\x12\x13.voltha.NullMessage\x1a\x11.voltha.Addresses\"\x12\x82\xd3\xe4\x93\x02\x0c\x12\n/addresses\x12\x42\n\nGetAddress\x12\n.voltha.ID\x1a\x0f.voltha.Address\"\x17\x82\xd3\xe4\x93\x02\x11\x12\x0f/addresses/{id}\x12H\n\rCreateAddress\x12\x0f.voltha.Address\x1a\x0f.voltha.Address\"\x15\x82\xd3\xe4\x93\x02\x0f\"\n/addresses:\x01*\x12I\n\rDeleteAddress\x12\n.voltha.ID\x1a\x13.voltha.NullMessage\"\x17\x82\xd3\xe4\x93\x02\x11*\x0f/addresses/{id}B<\n\x13org.opencord.volthaB\x0cVolthaProtos\xaa\x02\x16Opencord.Voltha.Volthab\x06proto3')
,
dependencies=[google_dot_api_dot_annotations__pb2.DESCRIPTOR,])
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
@@ -48,12 +48,124 @@
],
containing_type=None,
options=None,
- serialized_start=134,
- serialized_end=187,
+ serialized_start=342,
+ serialized_end=395,
)
_sym_db.RegisterEnumDescriptor(_HEALTHSTATUS_HEALTHSTATE)
+_SCHEMA_PROTOSENTRY = _descriptor.Descriptor(
+ name='ProtosEntry',
+ full_name='voltha.Schema.ProtosEntry',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='key', full_name='voltha.Schema.ProtosEntry.key', index=0,
+ number=1, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='value', full_name='voltha.Schema.ProtosEntry.value', index=1,
+ number=2, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=_descriptor._ParseOptions(descriptor_pb2.MessageOptions(), _b('8\001')),
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=163,
+ serialized_end=208,
+)
+
+_SCHEMA_DESCRIPTORSENTRY = _descriptor.Descriptor(
+ name='DescriptorsEntry',
+ full_name='voltha.Schema.DescriptorsEntry',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='key', full_name='voltha.Schema.DescriptorsEntry.key', index=0,
+ number=1, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='value', full_name='voltha.Schema.DescriptorsEntry.value', index=1,
+ number=2, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=_descriptor._ParseOptions(descriptor_pb2.MessageOptions(), _b('8\001')),
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=210,
+ serialized_end=260,
+)
+
+_SCHEMA = _descriptor.Descriptor(
+ name='Schema',
+ full_name='voltha.Schema',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='protos', full_name='voltha.Schema.protos', index=0,
+ number=1, type=11, cpp_type=10, label=3,
+ has_default_value=False, default_value=[],
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='descriptors', full_name='voltha.Schema.descriptors', index=1,
+ number=2, type=11, cpp_type=10, label=3,
+ has_default_value=False, default_value=[],
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[_SCHEMA_PROTOSENTRY, _SCHEMA_DESCRIPTORSENTRY, ],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=55,
+ serialized_end=260,
+)
+
+
_NULLMESSAGE = _descriptor.Descriptor(
name='NullMessage',
full_name='voltha.NullMessage',
@@ -73,8 +185,8 @@
extension_ranges=[],
oneofs=[
],
- serialized_start=54,
- serialized_end=67,
+ serialized_start=262,
+ serialized_end=275,
)
@@ -105,8 +217,8 @@
extension_ranges=[],
oneofs=[
],
- serialized_start=69,
- serialized_end=187,
+ serialized_start=277,
+ serialized_end=395,
)
@@ -178,8 +290,8 @@
extension_ranges=[],
oneofs=[
],
- serialized_start=189,
- serialized_end=302,
+ serialized_start=397,
+ serialized_end=510,
)
@@ -209,8 +321,8 @@
extension_ranges=[],
oneofs=[
],
- serialized_start=304,
- serialized_end=351,
+ serialized_start=512,
+ serialized_end=559,
)
@@ -268,8 +380,8 @@
extension_ranges=[],
oneofs=[
],
- serialized_start=354,
- serialized_end=513,
+ serialized_start=562,
+ serialized_end=721,
)
@@ -299,16 +411,21 @@
extension_ranges=[],
oneofs=[
],
- serialized_start=515,
- serialized_end=531,
+ serialized_start=723,
+ serialized_end=739,
)
+_SCHEMA_PROTOSENTRY.containing_type = _SCHEMA
+_SCHEMA_DESCRIPTORSENTRY.containing_type = _SCHEMA
+_SCHEMA.fields_by_name['protos'].message_type = _SCHEMA_PROTOSENTRY
+_SCHEMA.fields_by_name['descriptors'].message_type = _SCHEMA_DESCRIPTORSENTRY
_HEALTHSTATUS.fields_by_name['state'].enum_type = _HEALTHSTATUS_HEALTHSTATE
_HEALTHSTATUS_HEALTHSTATE.containing_type = _HEALTHSTATUS
_ADDRESSES.fields_by_name['addresses'].message_type = _ADDRESS
_MORECOMPLEX.fields_by_name['health'].message_type = _HEALTHSTATUS
_MORECOMPLEX.fields_by_name['children'].message_type = _MORECOMPLEX
_MORECOMPLEX.fields_by_name['address'].message_type = _ADDRESS
+DESCRIPTOR.message_types_by_name['Schema'] = _SCHEMA
DESCRIPTOR.message_types_by_name['NullMessage'] = _NULLMESSAGE
DESCRIPTOR.message_types_by_name['HealthStatus'] = _HEALTHSTATUS
DESCRIPTOR.message_types_by_name['Address'] = _ADDRESS
@@ -316,6 +433,29 @@
DESCRIPTOR.message_types_by_name['MoreComplex'] = _MORECOMPLEX
DESCRIPTOR.message_types_by_name['ID'] = _ID
+Schema = _reflection.GeneratedProtocolMessageType('Schema', (_message.Message,), dict(
+
+ ProtosEntry = _reflection.GeneratedProtocolMessageType('ProtosEntry', (_message.Message,), dict(
+ DESCRIPTOR = _SCHEMA_PROTOSENTRY,
+ __module__ = 'voltha_pb2'
+ # @@protoc_insertion_point(class_scope:voltha.Schema.ProtosEntry)
+ ))
+ ,
+
+ DescriptorsEntry = _reflection.GeneratedProtocolMessageType('DescriptorsEntry', (_message.Message,), dict(
+ DESCRIPTOR = _SCHEMA_DESCRIPTORSENTRY,
+ __module__ = 'voltha_pb2'
+ # @@protoc_insertion_point(class_scope:voltha.Schema.DescriptorsEntry)
+ ))
+ ,
+ DESCRIPTOR = _SCHEMA,
+ __module__ = 'voltha_pb2'
+ # @@protoc_insertion_point(class_scope:voltha.Schema)
+ ))
+_sym_db.RegisterMessage(Schema)
+_sym_db.RegisterMessage(Schema.ProtosEntry)
+_sym_db.RegisterMessage(Schema.DescriptorsEntry)
+
NullMessage = _reflection.GeneratedProtocolMessageType('NullMessage', (_message.Message,), dict(
DESCRIPTOR = _NULLMESSAGE,
__module__ = 'voltha_pb2'
@@ -361,6 +501,10 @@
DESCRIPTOR.has_options = True
DESCRIPTOR._options = _descriptor._ParseOptions(descriptor_pb2.FileOptions(), _b('\n\023org.opencord.volthaB\014VolthaProtos\252\002\026Opencord.Voltha.Voltha'))
+_SCHEMA_PROTOSENTRY.has_options = True
+_SCHEMA_PROTOSENTRY._options = _descriptor._ParseOptions(descriptor_pb2.MessageOptions(), _b('8\001'))
+_SCHEMA_DESCRIPTORSENTRY.has_options = True
+_SCHEMA_DESCRIPTORSENTRY._options = _descriptor._ParseOptions(descriptor_pb2.MessageOptions(), _b('8\001'))
import grpc
from grpc.beta import implementations as beta_implementations
from grpc.beta import interfaces as beta_interfaces
@@ -368,7 +512,98 @@
from grpc.framework.interfaces.face import utilities as face_utilities
+class SchemaServiceStub(object):
+ """Schema services
+ """
+
+ def __init__(self, channel):
+ """Constructor.
+
+ Args:
+ channel: A grpc.Channel.
+ """
+ self.GetSchema = channel.unary_unary(
+ '/voltha.SchemaService/GetSchema',
+ request_serializer=NullMessage.SerializeToString,
+ response_deserializer=Schema.FromString,
+ )
+
+
+class SchemaServiceServicer(object):
+ """Schema services
+ """
+
+ def GetSchema(self, request, context):
+ """Return active grpc schemas
+ """
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+
+def add_SchemaServiceServicer_to_server(servicer, server):
+ rpc_method_handlers = {
+ 'GetSchema': grpc.unary_unary_rpc_method_handler(
+ servicer.GetSchema,
+ request_deserializer=NullMessage.FromString,
+ response_serializer=Schema.SerializeToString,
+ ),
+ }
+ generic_handler = grpc.method_handlers_generic_handler(
+ 'voltha.SchemaService', rpc_method_handlers)
+ server.add_generic_rpc_handlers((generic_handler,))
+
+
+class BetaSchemaServiceServicer(object):
+ """Schema services
+ """
+ def GetSchema(self, request, context):
+ """Return active grpc schemas
+ """
+ context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)
+
+
+class BetaSchemaServiceStub(object):
+ """Schema services
+ """
+ def GetSchema(self, request, timeout, metadata=None, with_call=False, protocol_options=None):
+ """Return active grpc schemas
+ """
+ raise NotImplementedError()
+ GetSchema.future = None
+
+
+def beta_create_SchemaService_server(servicer, pool=None, pool_size=None, default_timeout=None, maximum_timeout=None):
+ request_deserializers = {
+ ('voltha.SchemaService', 'GetSchema'): NullMessage.FromString,
+ }
+ response_serializers = {
+ ('voltha.SchemaService', 'GetSchema'): Schema.SerializeToString,
+ }
+ method_implementations = {
+ ('voltha.SchemaService', 'GetSchema'): face_utilities.unary_unary_inline(servicer.GetSchema),
+ }
+ server_options = beta_implementations.server_options(request_deserializers=request_deserializers, response_serializers=response_serializers, thread_pool=pool, thread_pool_size=pool_size, default_timeout=default_timeout, maximum_timeout=maximum_timeout)
+ return beta_implementations.server(method_implementations, options=server_options)
+
+
+def beta_create_SchemaService_stub(channel, host=None, metadata_transformer=None, pool=None, pool_size=None):
+ request_serializers = {
+ ('voltha.SchemaService', 'GetSchema'): NullMessage.SerializeToString,
+ }
+ response_deserializers = {
+ ('voltha.SchemaService', 'GetSchema'): Schema.FromString,
+ }
+ cardinalities = {
+ 'GetSchema': cardinality.Cardinality.UNARY_UNARY,
+ }
+ stub_options = beta_implementations.stub_options(host=host, metadata_transformer=metadata_transformer, request_serializers=request_serializers, response_deserializers=response_deserializers, thread_pool=pool, thread_pool_size=pool_size)
+ return beta_implementations.dynamic_stub(channel, 'voltha.SchemaService', cardinalities, options=stub_options)
+
+
class HealthServiceStub(object):
+ """Health related services
+ """
def __init__(self, channel):
"""Constructor.
@@ -384,6 +619,8 @@
class HealthServiceServicer(object):
+ """Health related services
+ """
def GetHealthStatus(self, request, context):
"""Return current health status of a Voltha instance
@@ -407,6 +644,8 @@
class BetaHealthServiceServicer(object):
+ """Health related services
+ """
def GetHealthStatus(self, request, context):
"""Return current health status of a Voltha instance
"""
@@ -414,6 +653,8 @@
class BetaHealthServiceStub(object):
+ """Health related services
+ """
def GetHealthStatus(self, request, timeout, metadata=None, with_call=False, protocol_options=None):
"""Return current health status of a Voltha instance
"""
diff --git a/voltha/northbound/grpc/grpc_client.py b/voltha/northbound/grpc/grpc_client.py
index fc2b316..60b0b6b 100644
--- a/voltha/northbound/grpc/grpc_client.py
+++ b/voltha/northbound/grpc/grpc_client.py
@@ -25,6 +25,17 @@
channel = grpc.insecure_channel('localhost:50055')
+ # Test fetch the schema
+ stub = voltha_pb2.SchemaServiceStub(channel)
+ res = stub.GetSchema(voltha_pb2.NullMessage())
+ print '\nSchema:\n'
+ for key in res.protos:
+ print '%s %s file begins %s\n' % (30 * '~', key, (35 - len(key)) * '~')
+ print res.protos[key]
+ print '%s %s file ends %s' % (30 * '~', key, (37 - len(key)) * '~')
+ for key in res.descriptors:
+ print '%s -> descriptor of %d bytes' % (key, len(res.descriptors[key]))
+
# Ping health state as an example
stub = voltha_pb2.HealthServiceStub(channel)
res = stub.GetHealthStatus(voltha_pb2.NullMessage())
diff --git a/voltha/northbound/grpc/grpc_server.py b/voltha/northbound/grpc/grpc_server.py
index 9e1e44e..5b1d4ca 100644
--- a/voltha/northbound/grpc/grpc_server.py
+++ b/voltha/northbound/grpc/grpc_server.py
@@ -16,16 +16,64 @@
"""gRPC server endpoint"""
import uuid
-
+from os.path import abspath, basename, dirname, join, walk
import grpc
from concurrent import futures
from structlog import get_logger
+import zlib
from voltha.core.protos import voltha_pb2
log = get_logger()
+class SchemaService(voltha_pb2.SchemaServiceServicer):
+
+ def __init__(self):
+ proto_map, descriptor_map = self._load_schema()
+ self.schema = voltha_pb2.Schema(
+ protos=proto_map,
+ descriptors=descriptor_map
+ )
+
+ def _load_schema(self):
+ """Pre-load schema file so that we can serve it up (file sizes
+ are small enough to do so
+ """
+ proto_dir = abspath(join(dirname(__file__), '../../core/protos'))
+
+ def find_files(dir, suffix):
+ proto_files = []
+ visitor = lambda _, d, fnames: proto_files.extend(
+ [join(d, fn) for fn in fnames if fn.endswith(suffix)])
+ walk(dir, visitor, None)
+ return proto_files
+
+ proto_map = {}
+ for fpath in find_files(proto_dir, '.proto'):
+ with open(fpath, 'r') as f:
+ content = f.read()
+ fname = basename(fpath)
+ # assure no two files have the same basename
+ assert fname not in proto_map
+ proto_map[fname] = content
+
+ descriptor_map = {}
+ for fpath in find_files(proto_dir, '.desc'):
+ with open(fpath, 'r') as f:
+ content = f.read()
+ fname = basename(fpath)
+ # assure no two files have the same basename
+ assert fname not in descriptor_map
+ descriptor_map[fname] = zlib.compress(content)
+
+ return proto_map, descriptor_map
+
+ def GetSchema(self, request, context):
+ """Return current schema files and descriptor"""
+ return self.schema
+
+
class HealthService(voltha_pb2.HealthServiceServicer):
def __init__(self, thread_pool):
@@ -91,6 +139,8 @@
HealthService(self.thread_pool), self.server)
voltha_pb2.add_ExampleServiceServicer_to_server(
ExampleService(self.thread_pool), self.server)
+ voltha_pb2.add_SchemaServiceServicer_to_server(
+ SchemaService(), self.server)
self.server.add_insecure_port('[::]:%s' % self.port)