Merge branch 'master' of github.com:open-cloud/xos
diff --git a/xos/configurations/cord-pod/cord-vtn-vsg.yaml b/xos/configurations/cord-pod/cord-vtn-vsg.yaml
index e3f73c6..a315e41 100644
--- a/xos/configurations/cord-pod/cord-vtn-vsg.yaml
+++ b/xos/configurations/cord-pod/cord-vtn-vsg.yaml
@@ -8,21 +8,23 @@
 topology_template:
   node_templates:
     # CORD Services
-    service_vtr:
+    service#vtr:
       type: tosca.nodes.Service
       properties:
           view_url: /admin/vtr/vtrservice/$id$/
           kind: vTR
+          replaces: service_vtr
 
-    service_volt:
+    service#volt:
       type: tosca.nodes.Service
       requirements:
           - vsg_tenant:
-              node: service_vsg
+              node: service#vsg
               relationship: tosca.relationships.TenantOfService
       properties:
           view_url: /admin/cord/voltservice/$id$/
           kind: vOLT
+          replaces: service_volt
 
     addresses_vsg:
       type: tosca.nodes.AddressPool
@@ -38,11 +40,11 @@
           gateway_ip: 10.168.1.1
           gateway_mac: 02:42:0a:a8:00:01
 
-    service_vsg:
+    service#vsg:
       type: tosca.nodes.VSGService
       requirements:
           - vrouter_tenant:
-              node: service_vrouter
+              node: service#vrouter
               relationship: tosca.relationships.TenantOfService
       properties:
           view_url: /admin/cord/vsgservice/$id$/
@@ -50,13 +52,15 @@
           public_key: { get_artifact: [ SELF, pubkey, LOCAL_FILE] }
           private_key_fn: /opt/xos/synchronizers/vcpe/vcpe_private_key
 #          node_label: label_vsg
+          replaces: service_vsg
       artifacts:
           pubkey: /opt/xos/synchronizers/vcpe/vcpe_public_key
 
-    service_vrouter:
+    service#vrouter:
       type: tosca.nodes.VRouterService
       properties:
           view_url: /admin/vrouter/vrouterservice/$id$/
+          replaces: service_vrouter
       requirements:
           - addresses_vsg:
               node: addresses_vsg
@@ -65,10 +69,11 @@
               node: addresses_exampleservice-public
               relationship: tosca.relationships.ProvidesAddresses
 
-    service_fabric:
+    service#fabric:
       type: tosca.nodes.FabricService
       properties:
           view_url: /admin/fabric/fabricservice/$id$/
+          replaces: service_fabric
 
     Private:
       type: tosca.nodes.NetworkTemplate
@@ -110,7 +115,7 @@
           network: noauto
       requirements:
           - vsg_service:
-              node: service_vsg
+              node: service#vsg
               relationship: tosca.relationships.MemberOfService
           - site:
               node: mysite
@@ -193,7 +198,7 @@
             c_tag: 111
         requirements:
             - provider_service:
-                node: service_volt
+                node: service#volt
                 relationship: tosca.relationships.MemberOfService
             - subscriber:
                 node: My House
diff --git a/xos/configurations/cord-pod/make-vtn-external-yaml.sh b/xos/configurations/cord-pod/make-vtn-external-yaml.sh
index 4c9e0ee..8d0885d 100644
--- a/xos/configurations/cord-pod/make-vtn-external-yaml.sh
+++ b/xos/configurations/cord-pod/make-vtn-external-yaml.sh
@@ -13,7 +13,7 @@
 topology_template:
   node_templates:
 
-    service_ONOS_CORD:
+    service#ONOS_CORD:
       type: tosca.nodes.ONOSService
       requirements:
       properties:
@@ -21,8 +21,9 @@
           view_url: /admin/onos/onosservice/\$id$/
           no_container: true
           rest_hostname: onos-cord
+          replaces: service_ONOS_CORD
 
-    service_vtn:
+    service#vtn:
       type: tosca.nodes.VTNService
       properties:
           view_url: /admin/vtn/vtnservice/\$id$/
@@ -35,6 +36,7 @@
           xosEndpoint: http://xos/
           xosUser: padmin@vicci.org
           xosPassword: letmein
+          replaces: service_vtn
 
 EOF
 
@@ -57,7 +59,7 @@
               node: $NODE
               relationship: tosca.relationships.TagsObject
           - service:
-              node: service_ONOS_CORD
+              node: service#ONOS_CORD
               relationship: tosca.relationships.MemberOfService
 
     # VTN dataPlaneIntf field for node $NODE
@@ -71,7 +73,7 @@
               node: $NODE
               relationship: tosca.relationships.TagsObject
           - service:
-              node: service_ONOS_CORD
+              node: service#ONOS_CORD
               relationship: tosca.relationships.MemberOfService
 
     # VTN dataPlaneIp field for node $NODE
@@ -85,7 +87,7 @@
               node: $NODE
               relationship: tosca.relationships.TagsObject
           - service:
-              node: service_ONOS_CORD
+              node: service#ONOS_CORD
               relationship: tosca.relationships.MemberOfService
 
 EOF
@@ -96,10 +98,10 @@
       type: tosca.nodes.ONOSVTNApp
       requirements:
           - onos_tenant:
-              node: service_ONOS_CORD
+              node: service#ONOS_CORD
               relationship: tosca.relationships.TenantOfService
           - vtn_service:
-              node: service_vtn
+              node: service#vtn
               relationship: tosca.relationships.UsedByService
       properties:
           dependencies: org.onosproject.drivers, org.onosproject.drivers.ovsdb, org.onosproject.openflow-base, org.onosproject.ovsdb-base, org.onosproject.dhcp, org.onosproject.cordvtn, org.onosproject.olt, org.onosproject.igmp, org.onosproject.cordmcast
diff --git a/xos/tosca/custom_types/xos.m4 b/xos/tosca/custom_types/xos.m4
index e6d77f1..e83a22f 100644
--- a/xos/tosca/custom_types/xos.m4
+++ b/xos/tosca/custom_types/xos.m4
@@ -16,7 +16,11 @@
             no-update:
                 type: boolean
                 default: false
-                description: Do not allow Tosca to update this object)
+                description: Do not allow Tosca to update this object
+            replaces:
+                type: string
+                required: false
+                descrption: Replaces/renames this object)
 # Service
 define(xos_base_service_caps,
             scalable:
diff --git a/xos/tosca/custom_types/xos.yaml b/xos/tosca/custom_types/xos.yaml
index 2bca51e..b41a6c7 100644
--- a/xos/tosca/custom_types/xos.yaml
+++ b/xos/tosca/custom_types/xos.yaml
@@ -41,6 +41,10 @@
                 type: boolean
                 default: false
                 description: Do not allow Tosca to update this object
+            replaces:
+                type: string
+                required: false
+                descrption: Replaces/renames this object
             kind:
                 type: string
                 default: generic
@@ -117,6 +121,10 @@
                 type: boolean
                 default: false
                 description: Do not allow Tosca to update this object
+            replaces:
+                type: string
+                required: false
+                descrption: Replaces/renames this object
             kind:
                 type: string
                 default: generic
@@ -288,6 +296,10 @@
                 type: boolean
                 default: false
                 description: Do not allow Tosca to update this object
+            replaces:
+                type: string
+                required: false
+                descrption: Replaces/renames this object
             kind:
                 type: string
                 default: generic
@@ -352,6 +364,10 @@
                 type: boolean
                 default: false
                 description: Do not allow Tosca to update this object
+            replaces:
+                type: string
+                required: false
+                descrption: Replaces/renames this object
             kind:
                 type: string
                 default: generic
@@ -410,6 +426,10 @@
                 type: boolean
                 default: false
                 description: Do not allow Tosca to update this object
+            replaces:
+                type: string
+                required: false
+                descrption: Replaces/renames this object
             kind:
                 type: string
                 default: generic
@@ -464,6 +484,10 @@
                 type: boolean
                 default: false
                 description: Do not allow Tosca to update this object
+            replaces:
+                type: string
+                required: false
+                descrption: Replaces/renames this object
             kind:
                 type: string
                 default: generic
@@ -518,6 +542,10 @@
                 type: boolean
                 default: false
                 description: Do not allow Tosca to update this object
+            replaces:
+                type: string
+                required: false
+                descrption: Replaces/renames this object
             kind:
                 type: string
                 default: generic
@@ -603,6 +631,10 @@
                 type: boolean
                 default: false
                 description: Do not allow Tosca to update this object
+            replaces:
+                type: string
+                required: false
+                descrption: Replaces/renames this object
             kind:
                 type: string
                 default: generic
@@ -657,6 +689,10 @@
                 type: boolean
                 default: false
                 description: Do not allow Tosca to update this object
+            replaces:
+                type: string
+                required: false
+                descrption: Replaces/renames this object
             kind:
                 type: string
                 default: generic
@@ -806,6 +842,10 @@
                 type: boolean
                 default: false
                 description: Do not allow Tosca to update this object
+            replaces:
+                type: string
+                required: false
+                descrption: Replaces/renames this object
             password:
                 type: string
                 required: false
@@ -864,6 +904,10 @@
                 type: boolean
                 default: false
                 description: Do not allow Tosca to update this object
+            replaces:
+                type: string
+                required: false
+                descrption: Replaces/renames this object
 
         capabilities:
             network_parameter_type:
@@ -893,6 +937,10 @@
                 type: boolean
                 default: false
                 description: Do not allow Tosca to update this object
+            replaces:
+                type: string
+                required: false
+                descrption: Replaces/renames this object
             visibility:
                 type: string
                 required: false
@@ -942,7 +990,11 @@
             no-update:
                 type: boolean
                 default: false
-                description: Do not allow Tosca to update this object

+                description: Do not allow Tosca to update this object
+            replaces:
+                type: string
+                required: false
+                descrption: Replaces/renames this object

             ip_version:

               type: integer

               required: no

@@ -1046,6 +1098,10 @@
                 type: boolean
                 default: false
                 description: Do not allow Tosca to update this object
+            replaces:
+                type: string
+                required: false
+                descrption: Replaces/renames this object
             accessControl:
                 type: string
                 default: allow all
@@ -1075,6 +1131,10 @@
                 type: boolean
                 default: false
                 description: Do not allow Tosca to update this object
+            replaces:
+                type: string
+                required: false
+                descrption: Replaces/renames this object
             addresses:
                 type: string
                 required: false
@@ -1138,6 +1198,10 @@
                 type: boolean
                 default: false
                 description: Do not allow Tosca to update this object
+            replaces:
+                type: string
+                required: false
+                descrption: Replaces/renames this object
             backend_type:
                 type: string
                 required: false
@@ -1199,6 +1263,10 @@
                 type: boolean
                 default: false
                 description: Do not allow Tosca to update this object
+            replaces:
+                type: string
+                required: false
+                descrption: Replaces/renames this object
             display_name:
                 type: string
                 required: false
@@ -1244,6 +1312,10 @@
                 type: boolean
                 default: false
                 description: Do not allow Tosca to update this object
+            replaces:
+                type: string
+                required: false
+                descrption: Replaces/renames this object
             enabled:
                 type: boolean
                 default: true
@@ -1290,6 +1362,10 @@
                 type: boolean
                 default: false
                 description: Do not allow Tosca to update this object
+            replaces:
+                type: string
+                required: false
+                descrption: Replaces/renames this object
         capabilities:
             node:
                 type: tosca.capabilities.xos.Node
@@ -1311,6 +1387,10 @@
                 type: boolean
                 default: false
                 description: Do not allow Tosca to update this object
+            replaces:
+                type: string
+                required: false
+                descrption: Replaces/renames this object
         capabilities:
             node:
                 type: tosca.capabilities.xos.NodeLabel
@@ -1332,6 +1412,10 @@
                 type: boolean
                 default: false
                 description: Do not allow Tosca to update this object
+            replaces:
+                type: string
+                required: false
+                descrption: Replaces/renames this object
             flavor:
                 type: string
                 required: false
@@ -1357,6 +1441,10 @@
                 type: boolean
                 default: false
                 description: Do not allow Tosca to update this object
+            replaces:
+                type: string
+                required: false
+                descrption: Replaces/renames this object
         capabilities:
             siterole:
                 type: tosca.capabilities.xos.SiteRole
@@ -1378,6 +1466,10 @@
                 type: boolean
                 default: false
                 description: Do not allow Tosca to update this object
+            replaces:
+                type: string
+                required: false
+                descrption: Replaces/renames this object
         capabilities:
             slicerole:
                 type: tosca.capabilities.xos.SliceRole
@@ -1399,6 +1491,10 @@
                 type: boolean
                 default: false
                 description: Do not allow Tosca to update this object
+            replaces:
+                type: string
+                required: false
+                descrption: Replaces/renames this object
         capabilities:
             tenantrole:
                 type: tosca.capabilities.xos.TenantRole
@@ -1420,6 +1516,10 @@
                 type: boolean
                 default: false
                 description: Do not allow Tosca to update this object
+            replaces:
+                type: string
+                required: false
+                descrption: Replaces/renames this object
         capabilities:
             deploymentrole:
                 type: tosca.capabilities.xos.DeploymentRole
@@ -1444,6 +1544,10 @@
                 type: boolean
                 default: false
                 description: Do not allow Tosca to update this object
+            replaces:
+                type: string
+                required: false
+                descrption: Replaces/renames this object
             enabled:
                 type: boolean
                 default: true
@@ -1469,6 +1573,10 @@
                 type: boolean
                 default: false
                 description: Do not allow Tosca to update this object
+            replaces:
+                type: string
+                required: false
+                descrption: Replaces/renames this object
             name:
                 type: string
                 required: true
diff --git a/xos/tosca/resources/xosresource.py b/xos/tosca/resources/xosresource.py
index 82514c9..012f814 100644
--- a/xos/tosca/resources/xosresource.py
+++ b/xos/tosca/resources/xosresource.py
@@ -2,6 +2,7 @@
 import pdb
 import json
 import subprocess
+import sys
 
 from core.models import User
 
@@ -90,6 +91,13 @@
             return None
         return objs[0]
 
+    def get_replaces_objs(self):
+        replaces = self.get_property_default("replaces", None)
+        if replaces:
+            return self.xos_model.objects.filter(**{self.name_field: replaces})
+        else:
+            return []
+
     def get_existing_objs(self):
         return self.xos_model.objects.filter(**{self.name_field: self.obj_name})
 
@@ -97,7 +105,25 @@
         return self.xos_model.__name__
 
     def create_or_update(self):
+        replaces_objs = self.get_replaces_objs()
         existing_objs = self.get_existing_objs()
+
+        if (replaces_objs and existing_objs):
+            ro = replaces_objs[0]
+            self.info("deleting %s:%s" % (self.get_model_class_name(), getattr(ro,self.name_field)))
+            ro.delete()
+
+            # in case we wanted to throw an error instead...
+            #self.error("CRITICAL ERROR: Both %s and %s exist!" % (getattr(ro,self.name_field), self.obj_name))
+            #sys.exit(-1)
+
+        if (replaces_objs and not existing_objs):
+            ro = replaces_objs[0]
+            self.info("renaming %s:%s to %s" % (self.get_model_class_name(), getattr(ro,self.name_field), self.obj_name))
+            setattr(ro, self.name_field, self.obj_name)
+            ro.save()
+            existing_objs = self.get_existing_objs()
+
         if existing_objs:
             if self.get_property_default("no-update", False):
                 self.info("%s:%s (%s) already exists. Skipping update due to 'no-update' property" % (self.get_model_class_name(), self.obj_name, self.full_name))