CORD-910 added RunTosca gRPC API
Change-Id: I657240df1d7c6d34da320295fecb61ce14cf964f
diff --git a/xos/grpc/apihelper.py b/xos/grpc/apihelper.py
index 04f22d2..6ce81b6 100644
--- a/xos/grpc/apihelper.py
+++ b/xos/grpc/apihelper.py
@@ -164,7 +164,7 @@
obj.delete()
return Empty()
- def authenticate(self, context):
+ def authenticate(self, context, required=False):
for (k, v) in context.invocation_metadata():
if (k.lower()=="authorization"):
(method, auth) = v.split(" ",1)
@@ -185,6 +185,8 @@
print "authenticated sessionid %s as %s" % (v, user)
return user
+ if required:
+ raise XOSPermissionDenied("This API requires authentication")
return None
diff --git a/xos/grpc/protos/utility.proto b/xos/grpc/protos/utility.proto
index 36b5ed0..4717581 100644
--- a/xos/grpc/protos/utility.proto
+++ b/xos/grpc/protos/utility.proto
@@ -15,6 +15,19 @@
string sessionid = 1;
};
+message ToscaRequest {
+ string recipe = 1;
+};
+
+message ToscaResponse {
+ enum ToscaStatus {
+ SUCCESS = 0;
+ ERROR = 1;
+ }
+ ToscaStatus status = 1;
+ string messages = 2;
+};
+
service utility {
rpc Login(LoginRequest) returns (LoginResponse) {
@@ -30,4 +43,18 @@
body: "*"
};
}
+
+ rpc RunTosca(ToscaRequest) returns (ToscaResponse) {
+ option (google.api.http) = {
+ post: "/xosapi/v1/utility/tosca"
+ body: "*"
+ };
+ }
+
+ rpc DestroyTosca(ToscaRequest) returns (ToscaResponse) {
+ option (google.api.http) = {
+ post: "/xosapi/v1/utility/destroy_tosca"
+ body: "*"
+ };
+ }
};
diff --git a/xos/grpc/tests/tosca.py b/xos/grpc/tests/tosca.py
new file mode 100644
index 0000000..cc4f6bd
--- /dev/null
+++ b/xos/grpc/tests/tosca.py
@@ -0,0 +1,61 @@
+import random
+import string
+import sys
+sys.path.append("..")
+
+import grpc_client
+from testconfig import *
+
+SLICE_NAME="mysite_" + ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(10))
+
+TOSCA_RECIPE="""tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: Just some test...
+
+imports:
+ - custom_types/xos.yaml
+
+topology_template:
+ node_templates:
+ mysite:
+ type: tosca.nodes.Site
+
+ %s:
+ type: tosca.nodes.Slice
+ requirements:
+ - slice:
+ node: mysite
+ relationship: tosca.relationships.MemberOfSite
+""" % SLICE_NAME
+
+print "tosca_test"
+
+c=grpc_client.SecureClient("xos-core.cord.lab", username=USERNAME, password=PASSWORD)
+request=grpc_client.ToscaRequest()
+request.recipe = TOSCA_RECIPE
+
+print "Execute"
+
+response=c.utility.RunTosca(request)
+
+if response.status == response.SUCCESS:
+ print " success"
+else:
+ print " failure"
+
+for line in response.messages.split("\n"):
+ print " %s" % line
+
+print "Destroy"
+
+response = c.utility.DestroyTosca(request)
+
+if response.status == response.SUCCESS:
+ print " success"
+else:
+ print " failure"
+
+for line in response.messages.split("\n"):
+ print " %s" % line
+
+print "Done"
diff --git a/xos/grpc/xos_utility_api.py b/xos/grpc/xos_utility_api.py
index eb580ac..f595849 100644
--- a/xos/grpc/xos_utility_api.py
+++ b/xos/grpc/xos_utility_api.py
@@ -1,5 +1,8 @@
import base64
+import os
+import sys
import time
+import traceback
from protos import utility_pb2
from google.protobuf.empty_pb2 import Empty
@@ -13,6 +16,12 @@
from xos.exceptions import *
from apihelper import XOSAPIHelperMixin
+# The Tosca engine expects to be run from /opt/xos/tosca/ or equivalent. It
+# needs some sys.path fixing up.
+import inspect
+currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
+toscadir = os.path.join(currentdir, "../tosca")
+
class UtilityService(utility_pb2.utilityServicer, XOSAPIHelperMixin):
def __init__(self, thread_pool):
self.thread_pool = thread_pool
@@ -49,3 +58,49 @@
s.save()
return Empty()
+ def RunTosca(self, request, context):
+ user=self.authenticate(context, required=True)
+
+ sys_path_save = sys.path
+ try:
+ sys.path.append(toscadir)
+ from tosca.engine import XOSTosca
+ xt = XOSTosca(request.recipe, parent_dir=toscadir, log_to_console=False)
+ xt.execute(user)
+ except:
+ response = utility_pb2.ToscaResponse()
+ response.status = response.ERROR
+ response.messages = traceback.format_exc()
+ return response
+ finally:
+ sys.path = sys_path_save
+
+ response = utility_pb2.ToscaResponse()
+ response.status = response.SUCCESS
+ response.messages = "\n".join(xt.log_msgs)
+
+ return response
+
+ def DestroyTosca(self, request, context):
+ user=self.authenticate(context, required=True)
+
+ sys_path_save = sys.path
+ try:
+ sys.path.append(toscadir)
+ from tosca.engine import XOSTosca
+ xt = XOSTosca(request.recipe, parent_dir=toscadir, log_to_console=False)
+ xt.destroy(user)
+ except:
+ response = utility_pb2.ToscaResponse()
+ response.status = response.ERROR
+ response.messages = traceback.format_exc()
+ return response
+ finally:
+ sys.path = sys_path_save
+
+ response = utility_pb2.ToscaResponse()
+ response.status = response.SUCCESS
+ response.messages = "\n".join(xt.log_msgs)
+
+ return response
+