blob: caeb9e6bd1c52ad69cba310c6b5cd07efb1efe1d [file] [log] [blame]
# Copyright 2017-present Open Networking Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Copyright 2017 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
"""gRPC server endpoint"""
import os
import sys
import uuid
from collections import OrderedDict
from os.path import abspath, basename, dirname, join, walk
import grpc
from concurrent import futures
import zlib
if __name__ == "__main__":
import django
sys.path.append('/opt/xos')
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "xos.settings")
from protos import xos_pb2, schema_pb2, modeldefs_pb2, utility_pb2
from xos_grpc_api import XosService
from xos_modeldefs_api import ModelDefsService
from xos_utility_api import UtilityService
from google.protobuf.empty_pb2 import Empty
from xos.logger import Logger, logging
logger = Logger(level=logging.INFO)
SERVER_KEY="/opt/cord_profile/core_api_key.pem"
SERVER_CERT="/opt/cord_profile/core_api_cert.pem"
SERVER_CA="/usr/local/share/ca-certificates/local_certs.crt"
#SERVER_KEY="certs/server.key"
#SERVER_CERT="certs/server.crt"
#SERVER_CA="certs/ca.crt"
class SchemaService(schema_pb2.SchemaServiceServicer):
def __init__(self, thread_pool):
self.thread_pool = thread_pool
protos = self._load_schema()
self.schemas = schema_pb2.Schemas(protos=protos,
swagger_from='xos.proto',
yang_from='xos.proto')
def stop(self):
pass
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__), './protos'))
def find_files(dir, suffix):
proto_files = [
join(dir, fname) for fname in os.listdir(dir)
if fname.endswith(suffix)
]
return proto_files
proto_map = OrderedDict() # to have deterministic data
for proto_file in find_files(proto_dir, '.proto'):
with open(proto_file, 'r') as f:
proto_content = f.read()
fname = basename(proto_file)
# assure no two files have the same basename
assert fname not in proto_map
desc_file = proto_file.replace('.proto', '.desc')
with open(desc_file, 'r') as f:
descriptor_content = zlib.compress(f.read())
proto_map[fname] = schema_pb2.ProtoFile(
file_name=fname,
proto=proto_content,
descriptor=descriptor_content
)
return proto_map.values()
def GetSchema(self, request, context):
"""Return current schema files and descriptor"""
return self.schemas
class XOSGrpcServer(object):
def __init__(self, port=50055):
self.port = port
logger.info('init-grpc-server port=%d' % self.port)
self.thread_pool = futures.ThreadPoolExecutor(max_workers=10)
self.server = grpc.server(self.thread_pool)
server_key = open(SERVER_KEY,"r").read()
server_cert = open(SERVER_CERT,"r").read()
server_ca = open(SERVER_CA,"r").read()
self.credentials = grpc.ssl_server_credentials([(server_key, server_cert)], server_ca, False)
self.services = []
def start(self):
logger.debug('starting')
# add each service unit to the server and also to the list
for activator_func, service_class in (
(schema_pb2.add_SchemaServiceServicer_to_server, SchemaService),
(xos_pb2.add_xosServicer_to_server, XosService),
(modeldefs_pb2.add_modeldefsServicer_to_server, ModelDefsService),
(utility_pb2.add_utilityServicer_to_server, UtilityService),
):
service = service_class(self.thread_pool)
self.register(activator_func, service)
# open port
self.server.add_insecure_port('[::]:%s' % self.port)
self.server.add_secure_port("[::]:50051", self.credentials)
# strat the server
self.server.start()
logger.info('started')
return self
def stop(self, grace=0):
logger.debug('stopping')
for service in self.services:
service.stop()
self.server.stop(grace)
logger.debug('stopped')
def register(self, activator_func, service):
"""
Allow late registration of gRPC servicers
:param activator_func: The gRPC "add_XYZServicer_to_server method
autogenerated by protoc.
:param service: The object implementing the service.
:return: None
"""
self.services.append(service)
activator_func(service, self.server)
def restart_chameleon():
import docker
def find_container(client, search_name):
for c in client.containers():
for c_name in c["Names"]:
if (search_name in c_name):
return c
return None
client=docker.from_env()
chameleon_container = find_container(client, "xos_chameleon_1")
if chameleon_container:
try:
# the first attempt always fails with 404 error
# docker-py bug?
client.restart(chameleon_container["Names"][0])
except:
client.restart(chameleon_container["Names"][0])
# This is to allow running the GRPC server in stand-alone mode
if __name__ == '__main__':
django.setup()
server = XOSGrpcServer().start()
restart_chameleon()
import time
_ONE_DAY_IN_SECONDS = 60 * 60 * 24
try:
while 1:
time.sleep(_ONE_DAY_IN_SECONDS)
except KeyboardInterrupt:
server.stop()