[CORD-1528] Allow to reference models already created

Change-Id: Icf1cab69e0939d84f7f9c01d774f4399df51a7a4
diff --git a/src/grpc_client/models_accessor.py b/src/grpc_client/models_accessor.py
index 29c2f11..188a9ce 100644
--- a/src/grpc_client/models_accessor.py
+++ b/src/grpc_client/models_accessor.py
@@ -11,14 +11,13 @@
         Give a Model Class Name and some data, check if that exits or instantiate a new one
         """
 
-
         if data.get('name'):
             used_key = 'name'
         else:
             used_key = data.keys()[0]
 
         if class_name not in RESOURCES:
-            raise Exception('[XOS-TOSCA] The model your tring to create (%s: %s, class: %s) is not know by xos-core' % (used_key, data[used_key], class_name))
+            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]
         models = cls.objects.filter(**{used_key: data[used_key]})
@@ -27,6 +26,10 @@
             print "[XOS-Tosca] Model %s already exist, retrieving instance..." % data[used_key]
             model = models[0]
         elif len(models) == 0:
+
+            if 'must-exist' in data and data['must-exist']:
+                raise Exception("[XOS-TOSCA] Model %s:%s has property 'must-exist' but cannot be found" % (class_name, data[used_key]))
+
             model = cls.objects.new()
             print "[XOS-Tosca] Model %s is new, creating new instance..." % data[used_key]
         else:
diff --git a/src/tosca/parser.py b/src/tosca/parser.py
index 029b6ed..7c4f429 100644
--- a/src/tosca/parser.py
+++ b/src/tosca/parser.py
@@ -1,4 +1,4 @@
-from toscaparser.tosca_template import ToscaTemplate
+from toscaparser.tosca_template import ToscaTemplate, ValidationError
 from default import TOSCA_RECIPES_DIR
 from grpc_client.resources import RESOURCES
 from grpc_client.models_accessor import GRPCModelsAccessor
@@ -89,6 +89,8 @@
         for line in msg.splitlines():
             if line.strip().startswith('MissingRequiredFieldError'):
                 readable.append(line)
+            if line.strip().startswith('UnknownFieldError'):
+                readable.append(line)
 
         if len(readable) > 0:
             return '/n'.join(readable)
@@ -162,7 +164,7 @@
                 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)
-                # [] populate model with data[[
+                # [] populate model with data
                 model = self.populate_model(model, data)
                 # [] check if the model has requirements
                 # [] if it has populate them
@@ -172,12 +174,11 @@
 
                 self.saved_model_by_name[recipe.name] = model
 
-        except Exception as e:
-            print e
+        except ValidationError as e:
             if e.message:
-                exception_msg = e.message
+                exception_msg = TOSCA_Parser._translate_exception(e.message)
             else:
-                exception_msg = str(e)
+                exception_msg = TOSCA_Parser._translate_exception(str(e))
             raise Exception(exception_msg)
 
 
diff --git a/src/tosca/xtarget/tosca.xtarget b/src/tosca/xtarget/tosca.xtarget
index 313874b..2cdec9c 100644
--- a/src/tosca/xtarget/tosca.xtarget
+++ b/src/tosca/xtarget/tosca.xtarget
@@ -9,22 +9,10 @@
             {{ m.name|lower }}:
                 type: tosca.capabilities.xos.{{ m.name }}
         properties:
-            no-delete:
+            must-exist:
                 type: boolean
                 default: false
-                description: Do not allow Tosca to delete this object
-            no-create:
-                type: boolean
-                default: false
-                description: Do not allow Tosca to create this object
-            no-update:
-                type: boolean
-                default: false
-                description: Do not allow Tosca to update this object
-            replaces:
-                type: string
-                required: false
-                descrption: Replaces/renames this object
+                description: Allow to reference existing models in TOSCA recipes
             {% for f in m.fields %}
             {%- if not f.link -%}
             {{ f.name }}:
diff --git a/test/test_grpc_models_accessor.py b/test/test_grpc_models_accessor.py
index 707b5ef..03e9285 100644
--- a/test/test_grpc_models_accessor.py
+++ b/test/test_grpc_models_accessor.py
@@ -31,7 +31,7 @@
         }
         with self.assertRaises(Exception) as e:
             GRPCModelsAccessor.get_model_from_classname('i-do-not-exists', data)
-        self.assertEqual(e.exception.message, "[XOS-TOSCA] The model your tring to create (name: test, class: i-do-not-exists) is not know by xos-core")
+        self.assertEqual(e.exception.message, "[XOS-TOSCA] The model you are trying to create (name: test, class: i-do-not-exists) is not know by xos-core")
 
     @patch.object(FakeResource.objects, "filter")
     @patch.object(FakeResource.objects, "new", MagicMock(return_value=FakeModel))
diff --git a/test/test_tosca_parser_e2e.py b/test/test_tosca_parser_e2e.py
index 78276f2..5438c76 100644
--- a/test/test_tosca_parser_e2e.py
+++ b/test/test_tosca_parser_e2e.py
@@ -130,4 +130,37 @@
 
         saved_user = parser.saved_model_by_name['user_test']
         self.assertEqual(saved_user.firstname, 'User')
-        self.assertEqual(saved_user.site_id, 1)
\ No newline at end of file
+        self.assertEqual(saved_user.site_id, 1)
+
+    @patch.dict(RESOURCES, mock_resources, clear=True)
+    @patch.object(FakeSite.objects, 'filter', MagicMock(return_value=[]))
+    def test_must_exist_fail(self):
+        """
+        [TOSCA_Parser] Should throw an error if an object with 'must_exist' does not exist
+        """
+        recipe = """
+        tosca_definitions_version: tosca_simple_yaml_1_0
+
+        description: Create a new site with one user
+
+        imports:
+           - custom_types/user.yaml
+           - custom_types/site.yaml
+
+        topology_template:
+          node_templates:
+
+            # Site
+            site_onlab:
+              type: tosca.nodes.Site
+              properties:
+                name: Open Networking Lab
+                must-exist: True
+        """
+
+        parser = TOSCA_Parser(recipe)
+
+        with self.assertRaises(Exception) as e:
+            parser.execute()
+
+        self.assertEqual(e.exception.message, "[XOS-TOSCA] Model Site:Open Networking Lab has property 'must-exist' but cannot be found")
diff --git a/test/tosca/must_exist.yaml b/test/tosca/must_exist.yaml
new file mode 100644
index 0000000..a6a720c
--- /dev/null
+++ b/test/tosca/must_exist.yaml
@@ -0,0 +1,33 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: Persist xos-sample-gui-extension
+
+imports:
+   - custom_types/user.yaml
+   - custom_types/site.yaml
+   - custom_types/xosguiextension.yaml
+
+topology_template:
+  node_templates:
+
+    # Site
+    site_onlab:
+      type: tosca.nodes.Site
+      properties:
+        name: Open Networking Lab
+        must-exist: True
+
+    # User
+    user_test:
+      type: tosca.nodes.User
+      properties:
+        username: test@opencord.org
+        email: test@opencord.org
+        password: mypwd
+        firstname: User
+        lastname: Test
+        is_admin: True
+      requirements:
+        - site:
+            node: site_onlab
+            relationship: tosca.relationships.BelongsToOne
\ No newline at end of file