--- /dev/null
+# Copyright 2018 Telefonica S.A.
+#
+# 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.
+
+FROM ubuntu:18.04
+
+# Set the working directory to /app
+WORKDIR /app/EE
+
+# Libraries used by the base osm defined ee
+RUN apt-get update && apt-get install -y git python3 python3-pip \
+ && python3 -m pip install --upgrade pip \
+ && python3 -m pip install -U grpcio-tools \
+ && python3 -m pip install -U grpclib \
+ && python3 -m pip install -U PyYAML
+
+# Copy the current directory contents into the container at /app/LCM
+ADD . /app/EE
+
+# Install as module
+RUN python3 -m pip install -e /app/EE
+
+# Install SNMP Generator and its dependencies
+#RUN apt-get install -y python3-pip unzip build-essential libsnmp-dev wget curl
+#RUN curl -s https://storage.googleapis.com/golang/go1.11.8.linux-amd64.tar.gz| tar -v -C /usr/local -xz
+#ENV PATH $PATH:/usr/local/go/bin
+#ENV GOPATH /go
+#RUN go get github.com/go-logfmt/logfmt \
+# && go get github.com/go-kit/kit/log
+#RUN wget -q https://github.com/prometheus/snmp_exporter/archive/v0.17.0.tar.gz -P /tmp/ \
+# && tar -C /tmp -xf /tmp/v0.17.0.tar.gz \
+# && (cd /tmp/snmp_exporter-0.17.0/generator && go build) \
+# && cp /tmp/snmp_exporter-0.17.0/generator/generator /usr/local/bin/snmp_generator
+
+EXPOSE 50051
+
+#CMD python3 -m osm_ee.frontend_server
+# For development
+CMD [ "bash", "-c", "while true; do /app/EE/osm_ee/scripts/ee_start.sh ; sleep 5; done" ]
--- /dev/null
+##
+# Copyright 2019 Telefonica Investigacion y Desarrollo, S.A.U.
+# This file is part of OSM
+# All Rights Reserved.
+#
+# 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.
+#
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact with: nfvlabs@tid.es
+##
+
+import asyncio
+import logging
+import yaml
+import os
+
+from osm_ee.vnf.vnf_ee import VnfEE
+
+
+class BaseEE:
+
+ RETURN_STATUS_LIST = ["OK", "PROCESSING", "ERROR"]
+ CONFIG_FILE = "/app/storage/config.yaml"
+ SSH_KEY_FILE = "~/.ssh/id_rsa.pub"
+ HEALTH_CHECK_ACTION = "health-check"
+
+ def __init__(self):
+ self.logger = logging.getLogger('osm_ee.base')
+
+ # Check if configuration is stored and load it
+ if os.path.exists(self.CONFIG_FILE):
+ with open(self.CONFIG_FILE, 'r') as file:
+ self.config_params = yaml.load(file, Loader=yaml.FullLoader)
+ self.logger.debug("Load existing config from file: {}".format(self.config_params))
+ else:
+ self.config_params = {}
+
+ self.vnf_ee = VnfEE(self.config_params)
+
+ async def get_ssh_key(self):
+ self.logger.debug("Obtain ssh key")
+ filename = os.path.expanduser(self.SSH_KEY_FILE)
+ with open(filename) as reader:
+ ssh_key = reader.read()
+ return ssh_key
+
+ async def run_action(self, id, name, params):
+ self.logger.debug("Execute action id: {}, name: {}, params: {}".format(id, name, params))
+
+ try:
+ # Health-check
+ if name == self.HEALTH_CHECK_ACTION:
+ yield "OK", "Health-check ok"
+ else:
+
+ # Obtain dynamically code to be executed
+ method = getattr(self.vnf_ee, name)
+
+ # Convert params from yaml format
+ action_params = yaml.safe_load(params)
+
+ if name == "config":
+ self.logger.debug("Store config info in file: {}".format(self.CONFIG_FILE))
+ self.config_params.update(action_params)
+ with open(self.CONFIG_FILE, 'w') as file:
+ config = yaml.dump(self.config_params, file)
+
+ async for return_status, detailed_message in method(id, action_params):
+ if return_status not in self.RETURN_STATUS_LIST:
+ yield "ERROR", "Invalid return status"
+ else:
+ yield return_status, str(detailed_message)
+ except AttributeError as e:
+ error_msg = "Action name: {} not implemented".format(name)
+ self.logger.error(error_msg)
+ yield "ERROR", error_msg
+ except Exception as e:
+ self.logger.error("Error executing action id, name: {},{}: {}".format(id, name, str(e)), exc_info=True)
+ yield "ERROR", str(e)
+
+
+if __name__ == '__main__':
+ logging.basicConfig(level=logging.DEBUG)
+
+ loop = asyncio.get_event_loop()
+ try:
+ ee = BaseEE()
+ id = "test1"
+ name = "touch2"
+ params = {"file_path": "/var/tmp/testfile1.txt"}
+ action = asyncio.ensure_future(ee.run_action(id, name, params))
+ loop.run_until_complete(action)
+ finally:
+ loop.close()
--- /dev/null
+##
+# Copyright 2019 Telefonica Investigacion y Desarrollo, S.A.U.
+# This file is part of OSM
+# All Rights Reserved.
+#
+# 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.
+#
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact with: nfvlabs@tid.es
+##
+
+class ExecEnvException(Exception):
+ """Exception thrown by the EE if the actions can't be invoked or there is any generic error"""
+
+class VnfException(Exception):
+ """Exception thrown by the Vnf EE code in case of error"""
\ No newline at end of file
--- /dev/null
+syntax = "proto3";
+
+option java_multiple_files = true;
+option java_package = "com.etsi.osm.lcm.osm_ee";
+option java_outer_classname = "GrpcExecutor";
+option objc_class_prefix = "OEE";
+
+package osm_ee;
+
+service FrontendExecutor {
+
+ // Execute action leaving open a channel for notifications
+ rpc RunPrimitive (PrimitiveRequest) returns (stream PrimitiveReply) {}
+
+ // Sends a greeting
+ rpc GetSshKey (SshKeyRequest) returns (SshKeyReply) {}
+}
+
+// Request parameters
+message PrimitiveRequest {
+ string id=1;
+ string name=2;
+ string params=3;
+}
+
+message PrimitiveReply {
+ string status=1;
+ string detailed_message=2;
+}
+
+// The request message containing the user's name.
+message SshKeyRequest {
+ // empty
+}
+
+// The response message containing the greetings
+message SshKeyReply {
+ string message = 1;
+}
--- /dev/null
+##
+# Copyright 2019 Telefonica Investigacion y Desarrollo, S.A.U.
+# This file is part of OSM
+# All Rights Reserved.
+#
+# 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.
+#
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact with: nfvlabs@tid.es
+##
+
+import sys
+import yaml
+import asyncio
+import uuid
+import traceback
+import os
+import socket
+
+from grpclib.client import Channel
+
+from osm_ee.frontend_pb2 import PrimitiveRequest, PrimitiveReply
+from osm_ee.frontend_pb2 import SshKeyRequest, SshKeyReply
+from osm_ee.frontend_grpc import FrontendExecutorStub
+
+
+async def frontend_client(host_name, port, primitive_name, params):
+
+ ip_addr = socket.gethostbyname(host_name)
+ channel = Channel(ip_addr, port)
+ try:
+ stub = FrontendExecutorStub(channel)
+
+ if (primitive_name == "get_ssh_key"):
+ print("Get ssh key")
+ reply: SshKeyReply = await stub.GetSshKey(SshKeyRequest())
+ print(reply.message)
+ else:
+ async with stub.RunPrimitive.open() as stream:
+ primitive_id = str(uuid.uuid1())
+ print("Execute primitive {}, params: {}".format(primitive_name, params))
+ await stream.send_message(
+ PrimitiveRequest(id=primitive_id, name=primitive_name, params=yaml.dump(params)), end=True)
+ async for reply in stream:
+ print(reply)
+ #replies = [reply async for reply in stream]
+ #print(replies)
+ except Exception as e:
+ print("Error executing primitive {}: {}".format(primitive_name, str(e)))
+ #print(traceback.format_exc())
+ finally:
+ channel.close()
+
+
+if __name__ == '__main__':
+
+ args = sys.argv[1:]
+ if (len(args) < 1):
+ print("Usage: host port primitive_name params")
+ else:
+ host_name = args[0]
+ port = args[1]
+ primitive_name = args[2]
+ arg_params = args[3] if len(args) >= 4 else ""
+ print(primitive_name)
+ print(arg_params)
+ params = yaml.safe_load(arg_params)
+
+ loop = asyncio.get_event_loop()
+ try:
+ task = asyncio.ensure_future(frontend_client(host_name, port, primitive_name, params))
+ loop.run_until_complete(task)
+ finally:
+ loop.close()
--- /dev/null
+# Generated by the Protocol Buffers compiler. DO NOT EDIT!
+# source: osm_ee/frontend.proto
+# plugin: grpclib.plugin.main
+import abc
+import typing
+
+import grpclib.const
+import grpclib.client
+if typing.TYPE_CHECKING:
+ import grpclib.server
+
+import osm_ee.frontend_pb2
+
+
+class FrontendExecutorBase(abc.ABC):
+
+ @abc.abstractmethod
+ async def RunPrimitive(self, stream: 'grpclib.server.Stream[osm_ee.frontend_pb2.PrimitiveRequest, osm_ee.frontend_pb2.PrimitiveReply]') -> None:
+ pass
+
+ @abc.abstractmethod
+ async def GetSshKey(self, stream: 'grpclib.server.Stream[osm_ee.frontend_pb2.SshKeyRequest, osm_ee.frontend_pb2.SshKeyReply]') -> None:
+ pass
+
+ def __mapping__(self) -> typing.Dict[str, grpclib.const.Handler]:
+ return {
+ '/osm_ee.FrontendExecutor/RunPrimitive': grpclib.const.Handler(
+ self.RunPrimitive,
+ grpclib.const.Cardinality.UNARY_STREAM,
+ osm_ee.frontend_pb2.PrimitiveRequest,
+ osm_ee.frontend_pb2.PrimitiveReply,
+ ),
+ '/osm_ee.FrontendExecutor/GetSshKey': grpclib.const.Handler(
+ self.GetSshKey,
+ grpclib.const.Cardinality.UNARY_UNARY,
+ osm_ee.frontend_pb2.SshKeyRequest,
+ osm_ee.frontend_pb2.SshKeyReply,
+ ),
+ }
+
+
+class FrontendExecutorStub:
+
+ def __init__(self, channel: grpclib.client.Channel) -> None:
+ self.RunPrimitive = grpclib.client.UnaryStreamMethod(
+ channel,
+ '/osm_ee.FrontendExecutor/RunPrimitive',
+ osm_ee.frontend_pb2.PrimitiveRequest,
+ osm_ee.frontend_pb2.PrimitiveReply,
+ )
+ self.GetSshKey = grpclib.client.UnaryUnaryMethod(
+ channel,
+ '/osm_ee.FrontendExecutor/GetSshKey',
+ osm_ee.frontend_pb2.SshKeyRequest,
+ osm_ee.frontend_pb2.SshKeyReply,
+ )
--- /dev/null
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: osm_ee/frontend.proto
+
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import message as _message
+from google.protobuf import reflection as _reflection
+from google.protobuf import symbol_database as _symbol_database
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor.FileDescriptor(
+ name='osm_ee/frontend.proto',
+ package='osm_ee',
+ syntax='proto3',
+ serialized_options=b'\n\027com.etsi.osm.lcm.osm_eeB\014GrpcExecutorP\001\242\002\003OEE',
+ serialized_pb=b'\n\x15osm_ee/frontend.proto\x12\x06osm_ee\"<\n\x10PrimitiveRequest\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0e\n\x06params\x18\x03 \x01(\t\":\n\x0ePrimitiveReply\x12\x0e\n\x06status\x18\x01 \x01(\t\x12\x18\n\x10\x64\x65tailed_message\x18\x02 \x01(\t\"\x0f\n\rSshKeyRequest\"\x1e\n\x0bSshKeyReply\x12\x0f\n\x07message\x18\x01 \x01(\t2\x93\x01\n\x10\x46rontendExecutor\x12\x44\n\x0cRunPrimitive\x12\x18.osm_ee.PrimitiveRequest\x1a\x16.osm_ee.PrimitiveReply\"\x00\x30\x01\x12\x39\n\tGetSshKey\x12\x15.osm_ee.SshKeyRequest\x1a\x13.osm_ee.SshKeyReply\"\x00\x42/\n\x17\x63om.etsi.osm.lcm.osm_eeB\x0cGrpcExecutorP\x01\xa2\x02\x03OEEb\x06proto3'
+)
+
+
+
+
+_PRIMITIVEREQUEST = _descriptor.Descriptor(
+ name='PrimitiveRequest',
+ full_name='osm_ee.PrimitiveRequest',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='id', full_name='osm_ee.PrimitiveRequest.id', 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,
+ serialized_options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='name', full_name='osm_ee.PrimitiveRequest.name', 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,
+ serialized_options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='params', full_name='osm_ee.PrimitiveRequest.params', index=2,
+ number=3, 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,
+ serialized_options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ serialized_options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=33,
+ serialized_end=93,
+)
+
+
+_PRIMITIVEREPLY = _descriptor.Descriptor(
+ name='PrimitiveReply',
+ full_name='osm_ee.PrimitiveReply',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='status', full_name='osm_ee.PrimitiveReply.status', 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,
+ serialized_options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='detailed_message', full_name='osm_ee.PrimitiveReply.detailed_message', 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,
+ serialized_options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ serialized_options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=95,
+ serialized_end=153,
+)
+
+
+_SSHKEYREQUEST = _descriptor.Descriptor(
+ name='SshKeyRequest',
+ full_name='osm_ee.SshKeyRequest',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ serialized_options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=155,
+ serialized_end=170,
+)
+
+
+_SSHKEYREPLY = _descriptor.Descriptor(
+ name='SshKeyReply',
+ full_name='osm_ee.SshKeyReply',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='message', full_name='osm_ee.SshKeyReply.message', 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,
+ serialized_options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ serialized_options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=172,
+ serialized_end=202,
+)
+
+DESCRIPTOR.message_types_by_name['PrimitiveRequest'] = _PRIMITIVEREQUEST
+DESCRIPTOR.message_types_by_name['PrimitiveReply'] = _PRIMITIVEREPLY
+DESCRIPTOR.message_types_by_name['SshKeyRequest'] = _SSHKEYREQUEST
+DESCRIPTOR.message_types_by_name['SshKeyReply'] = _SSHKEYREPLY
+_sym_db.RegisterFileDescriptor(DESCRIPTOR)
+
+PrimitiveRequest = _reflection.GeneratedProtocolMessageType('PrimitiveRequest', (_message.Message,), {
+ 'DESCRIPTOR' : _PRIMITIVEREQUEST,
+ '__module__' : 'osm_ee.frontend_pb2'
+ # @@protoc_insertion_point(class_scope:osm_ee.PrimitiveRequest)
+ })
+_sym_db.RegisterMessage(PrimitiveRequest)
+
+PrimitiveReply = _reflection.GeneratedProtocolMessageType('PrimitiveReply', (_message.Message,), {
+ 'DESCRIPTOR' : _PRIMITIVEREPLY,
+ '__module__' : 'osm_ee.frontend_pb2'
+ # @@protoc_insertion_point(class_scope:osm_ee.PrimitiveReply)
+ })
+_sym_db.RegisterMessage(PrimitiveReply)
+
+SshKeyRequest = _reflection.GeneratedProtocolMessageType('SshKeyRequest', (_message.Message,), {
+ 'DESCRIPTOR' : _SSHKEYREQUEST,
+ '__module__' : 'osm_ee.frontend_pb2'
+ # @@protoc_insertion_point(class_scope:osm_ee.SshKeyRequest)
+ })
+_sym_db.RegisterMessage(SshKeyRequest)
+
+SshKeyReply = _reflection.GeneratedProtocolMessageType('SshKeyReply', (_message.Message,), {
+ 'DESCRIPTOR' : _SSHKEYREPLY,
+ '__module__' : 'osm_ee.frontend_pb2'
+ # @@protoc_insertion_point(class_scope:osm_ee.SshKeyReply)
+ })
+_sym_db.RegisterMessage(SshKeyReply)
+
+
+DESCRIPTOR._options = None
+
+_FRONTENDEXECUTOR = _descriptor.ServiceDescriptor(
+ name='FrontendExecutor',
+ full_name='osm_ee.FrontendExecutor',
+ file=DESCRIPTOR,
+ index=0,
+ serialized_options=None,
+ serialized_start=205,
+ serialized_end=352,
+ methods=[
+ _descriptor.MethodDescriptor(
+ name='RunPrimitive',
+ full_name='osm_ee.FrontendExecutor.RunPrimitive',
+ index=0,
+ containing_service=None,
+ input_type=_PRIMITIVEREQUEST,
+ output_type=_PRIMITIVEREPLY,
+ serialized_options=None,
+ ),
+ _descriptor.MethodDescriptor(
+ name='GetSshKey',
+ full_name='osm_ee.FrontendExecutor.GetSshKey',
+ index=1,
+ containing_service=None,
+ input_type=_SSHKEYREQUEST,
+ output_type=_SSHKEYREPLY,
+ serialized_options=None,
+ ),
+])
+_sym_db.RegisterServiceDescriptor(_FRONTENDEXECUTOR)
+
+DESCRIPTOR.services_by_name['FrontendExecutor'] = _FRONTENDEXECUTOR
+
+# @@protoc_insertion_point(module_scope)
--- /dev/null
+##
+# Copyright 2019 Telefonica Investigacion y Desarrollo, S.A.U.
+# This file is part of OSM
+# All Rights Reserved.
+#
+# 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.
+#
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact with: nfvlabs@tid.es
+##
+
+import asyncio
+import logging
+import os
+
+from grpclib.utils import graceful_exit
+from grpclib.server import Server, Stream
+
+from osm_ee.frontend_grpc import FrontendExecutorBase
+from osm_ee.frontend_pb2 import PrimitiveRequest, PrimitiveReply
+from osm_ee.frontend_pb2 import SshKeyRequest, SshKeyReply
+
+from osm_ee.base_ee import BaseEE
+import osm_ee.util.util_ee as util_ee
+
+
+class FrontendExecutor(FrontendExecutorBase):
+
+ def __init__(self):
+ self.logger = logging.getLogger('osm_ee.frontend_server')
+ self.base_ee = BaseEE()
+
+ async def RunPrimitive(self, stream: Stream[PrimitiveRequest, PrimitiveReply]) -> None:
+ request = await stream.recv_message()
+ try:
+ self.logger.debug(f'Run primitive: id {request.id}, name: {request.name}, params: {request.params}')
+ async for status, detailed_message in self.base_ee.run_action(request.id, request.name, request.params):
+ self.logger.debug(f'Send response {status}, {detailed_message}')
+ await stream.send_message(
+ PrimitiveReply(status=status, detailed_message=detailed_message))
+ except Exception as e:
+ self.logger.debug(f'Error executing primitive: id {request.id}, name: {request.name}, error_msg: {str(e)}')
+ await stream.send_message(
+ PrimitiveReply(status="ERROR", detailed_message=str(e)))
+
+ async def GetSshKey(self, stream: Stream[SshKeyRequest, SshKeyReply]) -> None:
+ request = await stream.recv_message()
+ assert request is not None
+ message = await self.base_ee.get_ssh_key()
+ await stream.send_message(SshKeyReply(message=message))
+
+
+async def main(*, host: str = '0.0.0.0', port: int = 50051) -> None:
+ logging.basicConfig()
+ logger = logging.getLogger('osm_ee')
+ logger.setLevel(logging.DEBUG)
+
+ # Generate ssh key
+ file_dir = os.path.expanduser("~/.ssh/id_rsa")
+ command = "ssh-keygen -q -t rsa -N '' -f {}".format(file_dir)
+ return_code, stdout, stderr = await util_ee.local_async_exec(command)
+ logger.debug("Generated ssh_key, return_code: {}".format(return_code))
+
+ # Start server
+ server = Server([FrontendExecutor()])
+ with graceful_exit([server]):
+ await server.start(host, port)
+ logging.getLogger('osm_ee.frontend_server').debug(f'Serving on {host}:{port}')
+ await server.wait_closed()
+
+
+if __name__ == '__main__':
+ loop = asyncio.get_event_loop()
+ try:
+ main_task = asyncio.ensure_future(main())
+ loop.run_until_complete(main_task)
+ finally:
+ loop.close()
--- /dev/null
+#!/bin/bash
+##
+# Copyright 2015 Telefonica Investigacion y Desarrollo, S.A.U.
+# 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.
+##
+
+# This script is intended for launching RO from a docker container.
+# It waits for mysql server ready, normally running on a separate container, ...
+# then it checks if database is present and creates it if needed.
+# Finally it launches RO server.
+
+EE_PATH=/app/EE
+
+# Install vnf vendor additional required libraries
+echo "Install additional libraries"
+bash ${EE_PATH}/osm_ee/vnf/install.sh
+
+# Start frontend
+echo "Starting frontend server"
+python3 -m osm_ee.frontend_server
--- /dev/null
+##
+# Copyright 2019 Telefonica Investigacion y Desarrollo, S.A.U.
+# This file is part of OSM
+# All Rights Reserved.
+#
+# 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.
+#
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact with: nfvlabs@tid.es
+##
+
+import logging
+import json
+from shlex import quote
+
+import osm_ee.util.util_ee as util_ee
+
+logger = logging.getLogger("osm_ee.util_ansible")
+
+
+async def execute_playbook(playbook_name: str, inventory: str, extra_vars: dict,
+ ) -> (int, str):
+
+ command = 'ansible-playbook --inventory={} --extra-vars {} {}'.format(quote(inventory),
+ quote(json.dumps(extra_vars)),
+ quote(playbook_name))
+
+ logger.debug("Command to be executed: {}".format(command))
+
+ return_code, stdout, stderr = await util_ee.local_async_exec(command)
+ logger.debug("Return code: {}".format(return_code))
+ logger.debug("stdout: {}".format(stdout))
+ logger.debug("stderr: {}".format(stderr))
+
+ return return_code, stdout, stderr
--- /dev/null
+##
+# Copyright 2019 Telefonica Investigacion y Desarrollo, S.A.U.
+# This file is part of OSM
+# All Rights Reserved.
+#
+# 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.
+#
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact with: nfvlabs@tid.es
+##
+
+import logging
+import asyncio
+from shlex import split
+
+logger = logging.getLogger("osm_ee.util")
+
+
+async def local_async_exec(command: str
+ ) -> (int, str, str):
+ """
+ Executed a local command using asyncio.
+ TODO - do not know yet if return error code, and stdout and strerr or just one of them
+ """
+ scommand = split(command)
+
+ logger.debug("Execute local command: {}".format(command))
+ process = await asyncio.create_subprocess_exec(
+ *scommand,
+ stdout=asyncio.subprocess.PIPE,
+ stderr=asyncio.subprocess.PIPE
+ )
+
+ # wait for command terminate
+ stdout, stderr = await process.communicate()
+
+ return_code = process.returncode
+ logger.debug("Return code: {}".format(return_code))
+
+ output = ""
+ if stdout:
+ output = stdout.decode()
+ logger.debug("Output: {}".format(output))
+
+ if stderr:
+ out_err = stderr.decode()
+ logger.debug("Stderr: {}".format(out_err))
+
+ return return_code, stdout, stderr
--- /dev/null
+#!/bin/bash
+##
+# Copyright 2015 Telefonica Investigacion y Desarrollo, S.A.U.
+# 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.
+##
+
+# This script is intended for launching RO from a docker container.
+# It waits for mysql server ready, normally running on a separate container, ...
+# then it checks if database is present and creates it if needed.
+# Finally it launches RO server.
+
+echo "Sample install.sh "
\ No newline at end of file
--- /dev/null
+##
+# Copyright 2019 Telefonica Investigacion y Desarrollo, S.A.U.
+# This file is part of OSM
+# All Rights Reserved.
+#
+# 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.
+#
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact with: nfvlabs@tid.es
+##
+
+import asyncio
+import logging
+
+from osm_ee.exceptions import VnfException
+
+
+class VnfEE:
+
+ def __init__(self, config_params):
+ self.logger = logging.getLogger('osm_ee.vnf')
+ self.config_params = config_params
+
+ async def config(self, id, params):
+ self.logger.debug("Execute action config params: {}".format(params))
+ # Config action is special, params are merged with previous config calls
+ self.config_params.update(params)
+ yield "OK", "Configured"
+
+ async def sleep(self, id, params):
+ self.logger.debug("Execute action sleep, params: {}".format(params))
+
+ for i in range(3):
+ await asyncio.sleep(5)
+ self.logger.debug("Temporal result return, params: {}".format(params))
+ yield "PROCESSING", f"Processing {i} action id {id}"
+ yield "OK", f"Processed action id {id}"
+
+ @staticmethod
+ def _check_required_params(params, required_params):
+ for required_param in required_params:
+ if required_param not in params:
+ raise VnfException("Missing required param: {}".format(required_param))
--- /dev/null
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+# Copyright 2018 Telefonica S.A.
+#
+# 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.
+
+from setuptools import setup
+
+_name = "osm_ee"
+
+_description = 'OSM Resource Orchestrator'
+_author = 'ETSI OSM'
+_author_email = 'illoret@indra.es'
+_maintainer = 'alfonso.tiernosepulveda'
+_maintainer_email = 'alfonso.tiernosepulveda@telefonica.com'
+_license = 'Apache 2.0'
+_url = 'TOBEDEFINED'
+_requirements = [
+ # Libraries needed by the code defined by osm
+ "PyYAML",
+ "grpcio-tools",
+ "grpclib",
+ "protobuf",
+
+ # Libraries defined by the vnf code, they should be in an external file
+ #"asyncssh",
+]
+
+setup(
+ name=_name,
+ #version_command=('0.1'), # TODO - replace for a git command
+ version='1.0',
+ description=_description,
+ long_description=open('README.rst').read(),
+ author=_author,
+ author_email=_author_email,
+ maintainer=_maintainer,
+ maintainer_email=_maintainer_email,
+ url=_url,
+ license=_license,
+ packages=[_name],
+ package_dir={_name: _name},
+
+ install_requires=_requirements,
+ include_package_data=True,
+ setup_requires=['setuptools-version-command'],
+)
\ No newline at end of file