[CORD-1502] [CORD-1516] Authenticating the user that is sending the
request and caching it's orm classes
Change-Id: I4754c1395d085ed0cf313c7fffebbd2d0b8c7fd4
diff --git a/src/grpc_client/main.py b/src/grpc_client/main.py
index 5612d76..b3e29b1 100644
--- a/src/grpc_client/main.py
+++ b/src/grpc_client/main.py
@@ -1,8 +1,9 @@
import functools
from xosapi.xos_grpc_client import SecureClient, InsecureClient
-from twisted.internet import reactor, defer
+from twisted.internet import defer
from resources import RESOURCES
from xosconfig import Config
+from twisted.internet import reactor
LOCAL_CERT = '/Users/teone/Sites/opencord/orchestration/xos-tosca/local_certs.crt'
@@ -12,13 +13,14 @@
self.grpc_secure_endpoint = Config.get('grpc.secure_endpoint')
self.grpc_insecure_endpoint = Config.get('grpc.insecure_endpoint')
- self.username = Config.get('grpc.admin_username')
- self.password = Config.get('grpc.admin_password')
- def setup_resources(self, client):
+ def setup_resources(self, client, key, deferred, recipe):
print "[XOS-TOSCA] Loading resources"
+ if key not in RESOURCES:
+ RESOURCES[key] = {}
for k in client.xos_orm.all_model_names:
- RESOURCES[k] = getattr(client.xos_orm, k)
+ RESOURCES[key][k] = getattr(client.xos_orm, k)
+ reactor.callLater(0, deferred.callback, recipe)
def start(self):
print "[XOS-TOSCA] Connecting to xos-core"
@@ -29,15 +31,23 @@
self.client.stop()
self.client.session_change = True
- if self.username and self.password:
- # NOTE if we authenticate users given the parameters in the rest request, do we need this?
- self.client = SecureClient(endpoint=self.grpc_secure_endpoint, username=self.username, password=self.password, cacert=LOCAL_CERT)
- else:
- self.client = InsecureClient(endpoint=self.grpc_insecure_endpoint)
+ self.client = InsecureClient(endpoint=self.grpc_insecure_endpoint)
- self.client.set_reconnect_callback(functools.partial(self.setup_resources, self.client))
+ self.client.set_reconnect_callback(functools.partial(deferred.callback, self.client))
self.client.start()
- # TODO can we call this once the client is setted up?
- reactor.callLater(12, deferred.callback, self.client)
- return deferred
\ No newline at end of file
+ return deferred
+
+ def create_secure_client(self, username, password, recipe):
+ """
+ This method will check if this combination of username/password already has stored orm classes in RESOURCES, otherwise create them
+ """
+ deferred = defer.Deferred()
+ key = "%s~%s" % (username, password)
+ if key in RESOURCES:
+ reactor.callLater(0, deferred.callback, recipe)
+ else:
+ client = SecureClient(endpoint=self.grpc_secure_endpoint, username=username, password=password, cacert=LOCAL_CERT)
+ client.set_reconnect_callback(functools.partial(self.setup_resources, client, key, deferred, recipe))
+ client.start()
+ return deferred
diff --git a/src/grpc_client/models_accessor.py b/src/grpc_client/models_accessor.py
index 188a9ce..82934e5 100644
--- a/src/grpc_client/models_accessor.py
+++ b/src/grpc_client/models_accessor.py
@@ -6,7 +6,7 @@
"""
@staticmethod
- def get_model_from_classname(class_name, data):
+ def get_model_from_classname(class_name, data, username, password):
"""
Give a Model Class Name and some data, check if that exits or instantiate a new one
"""
@@ -16,10 +16,13 @@
else:
used_key = data.keys()[0]
- if class_name not in RESOURCES:
+ key = "%s~%s" % (username, password)
+ if not key in RESOURCES:
+ raise Exception("[XOS-TOSCA] User '%s' does not have ready resources" % username)
+ if class_name not in RESOURCES[key]:
raise Exception('[XOS-TOSCA] The model you are trying to create (%s: %s, class: %s) is not know by xos-core' % (used_key, data[used_key], class_name))
- cls = RESOURCES[class_name]
+ cls = RESOURCES[key][class_name]
models = cls.objects.filter(**{used_key: data[used_key]})
if len(models) == 1:
diff --git a/src/main.py b/src/main.py
index e9e8c10..92c21ee 100644
--- a/src/main.py
+++ b/src/main.py
@@ -2,7 +2,7 @@
from grpc_client.main import GRPC_Client
from tosca.generator import TOSCA_Generator
from web_server.main import TOSCA_WebServer
-from twisted.internet import reactor, defer
+from twisted.internet import defer
from xosconfig import Config
current_dir = os.path.dirname(os.path.realpath(__file__))
@@ -21,7 +21,6 @@
TOSCA_Generator().generate(client)
- reactor.callLater(0, TOSCA_WebServer)
return deferred
@@ -31,7 +30,8 @@
grpc_setup = GRPC_Client().start()
grpc_setup.addCallback(self.generate_tosca)
- reactor.run()
+ # NOTE that TOSCA_WebServer create a Klein app that call reactor.run()
+ TOSCA_WebServer()
if __name__ == '__main__':
diff --git a/src/tosca/parser.py b/src/tosca/parser.py
index 7c4f429..725d259 100644
--- a/src/tosca/parser.py
+++ b/src/tosca/parser.py
@@ -2,6 +2,8 @@
from default import TOSCA_RECIPES_DIR
from grpc_client.resources import RESOURCES
from grpc_client.models_accessor import GRPCModelsAccessor
+from grpc._channel import _Rendezvous
+import json
class TOSCA_Parser:
@@ -125,7 +127,11 @@
setattr(model, "%s_id" % class_name, related_model.id)
return model
- def __init__(self, recipe):
+ def __init__(self, recipe, username, password):
+
+ # store username/password combination to read resources
+ self.username = username
+ self.password = password
# the template returned by TOSCA-Parser
self.template = None
@@ -161,9 +167,7 @@
data = recipe.templates[recipe.name]['properties']
# [] get model by class name
class_name = recipe.type.replace("tosca.nodes.", "")
- if class_name not in RESOURCES:
- raise Exception("Nodetemplate %s's type %s is not a known resource" % (recipe.name, class_name))
- model = GRPCModelsAccessor.get_model_from_classname(class_name, data)
+ model = GRPCModelsAccessor.get_model_from_classname(class_name, data, self.username, self.password)
# [] populate model with data
model = self.populate_model(model, data)
# [] check if the model has requirements
@@ -181,4 +185,13 @@
exception_msg = TOSCA_Parser._translate_exception(str(e))
raise Exception(exception_msg)
+ except _Rendezvous, e:
+ try:
+ exception_msg = json.loads(e._state.details)["error"]
+ except Exception:
+ exception_msg = e._state.details
+ raise Exception(exception_msg)
+ except Exception, e:
+ raise e
+
diff --git a/src/web_server/main.py b/src/web_server/main.py
index 4896a71..aaf2c66 100644
--- a/src/web_server/main.py
+++ b/src/web_server/main.py
@@ -1,5 +1,7 @@
-from flask import Flask, make_response, request
from tosca.parser import TOSCA_Parser
+from grpc_client.main import GRPC_Client
+from klein import Klein
+import functools
BANNER = """
_ ______ _____ __________ _____ _________
@@ -10,23 +12,32 @@
"""
class TOSCA_WebServer:
- app = Flask('TOSCA-Web-Server')
- @app.route("/", methods=['GET', 'POST'])
- def home():
- if request.method == 'GET':
- response = make_response(BANNER)
- response.headers["content-type"] = "text/plain"
- return response
- else:
- try:
- # print request.headers['xos-password']
- parser = TOSCA_Parser(request.get_data())
- parser.execute()
- response_text = "Created models: %s" % str(parser.ordered_models_name)
- return make_response(response_text, 201)
- except Exception, e:
- return make_response(e.message, 400)
+ app = Klein()
+
+ def execute_tosca(self, recipe):
+ try:
+ self.parser.execute()
+ response_text = "Created models: %s" % str(self.parser.ordered_models_name)
+ return response_text
+ except Exception, e:
+ return e.message
+
+ @app.route('/', methods=['GET'])
+ def index(self, request):
+ return BANNER
+
+ @app.route('/run', methods=['POST'])
+ def execute(self, request):
+ recipe = request.content.read()
+ headers = request.getAllHeaders()
+ username = headers['xos-username']
+ password = headers['xos-password']
+
+ d = GRPC_Client().create_secure_client(username, password, recipe)
+ self.parser = TOSCA_Parser(recipe, username, password)
+ d.addCallback(self.execute_tosca)
+ return d
def __init__(self):
- self.app.run(host='localhost', port='9200')
\ No newline at end of file
+ self.app.run('localhost', '9200')
\ No newline at end of file
diff --git a/src/xos-tosca-config-schema.yaml b/src/xos-tosca-config-schema.yaml
index 5eb221f..277ee08 100644
--- a/src/xos-tosca-config-schema.yaml
+++ b/src/xos-tosca-config-schema.yaml
@@ -5,12 +5,6 @@
grpc:
type: map
map:
- admin_username:
- type: str
- required: True
- admin_password:
- type: str
- required: True
secure_endpoint:
type: str
required: True
diff --git a/src/xos-tosca-config.yaml b/src/xos-tosca-config.yaml
index 2555112..6ed2b43 100644
--- a/src/xos-tosca-config.yaml
+++ b/src/xos-tosca-config.yaml
@@ -1,6 +1,4 @@
name: xos-tosca
grpc:
- admin_username: "xosadmin@opencord.org"
- admin_password: "rk1UYDHZXbu6KVCMkhmV"
secure_endpoint: "xos-core.opencord.org:50051"
insecure_endpoint: "xos-core.opencord.org:50055"