Merge branch 'feature/fixture-cleanup'
diff --git a/xos/configurations/cord-pod/Makefile b/xos/configurations/cord-pod/Makefile
index 3745f93..ce1baf8 100644
--- a/xos/configurations/cord-pod/Makefile
+++ b/xos/configurations/cord-pod/Makefile
@@ -8,10 +8,10 @@
 	sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/nodes.yaml
 	sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/images.yaml
 
-vtn:
+vtn: vtn-external.yaml
 	sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/vtn-external.yaml
 
-cord: virtualbng_json
+cord: 
 	sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/mgmt-net.yaml
 	sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/cord-vtn-vsg.yaml
 
@@ -27,6 +27,9 @@
 images.yaml:
 	export SETUPDIR=.; bash ../common/make-images-yaml.sh
 
+vtn-external.yaml:
+	export SETUPDIR=.; bash ./make-vtn-external-yaml.sh
+
 virtualbng_json:
 	export SETUPDIR=.; bash ./make-virtualbng-json.sh
 
diff --git a/xos/configurations/cord-pod/README.md b/xos/configurations/cord-pod/README.md
index c300416..d5051c9 100644
--- a/xos/configurations/cord-pod/README.md
+++ b/xos/configurations/cord-pod/README.md
@@ -31,7 +31,7 @@
 To set up OpenStack, follow the instructions in the
 [README.md](https://github.com/open-cloud/openstack-cluster-setup/blob/master/README.md)
 file of the [open-cloud/openstack-cluster-setup](https://github.com/open-cloud/openstack-cluster-setup/)
-repository.  If you're just getting started with CORD, it's probably best to begin with the 
+repository.  If you're just getting started with CORD, it's probably best to begin with the
 single-node CORD test environment to familiarize yourself with the overall setup.
 
 **NOTE: In order to use the cord-pod configuration, you must set up OpenStack using the above recipe.**
@@ -73,7 +73,7 @@
 ubuntu@xos:~$ cd xos/xos/configurations/cord-pod
 ```
 
-Next, check that the following files exist in this directory 
+Next, check that the following files exist in this directory
 (they will have been put there for you by the cluster installation scripts):
 
  * *admin-openrc.sh*: Admin credentials for your OpenStack cloud
@@ -93,37 +93,37 @@
 being sync'ed with OpenStack.  Log into the GUI and select *Users*
 at left.  Make sure there is a green check next to `padmin@vicci.org`.
 
-Next, you may need to edit `vtn-external.yml` so that `rest_hostname:`
-points to the host where ONOS should run the VTN app.  Then run:
+> If you are **not** building the single-node development POD, the next
+> step is to create and edit the VTN configuration.  Run `make vtn-external.yaml`
+> then edit the `vtn-external.yml` TOSCA file.  The `rest_hostname:`
+> field points to the host where ONOS should run the VTN app.  The
+> fields in the `service_vtn` and the objects of type `tosca.nodes.Tag`
+> correspond to the VTN fields listed
+> on [the CORD VTN page on the ONOS Wiki](https://wiki.onosproject.org/display/ONOS/CORD+VTN),
+> under the **ONOS Settings** heading; refer there for the fields'
+> meanings.  
+
+Then run:
 
 ```
 ubuntu@xos:~/xos/xos/configurations/cord-pod$ make vtn
 ```
 The above step configures the ONOS VTN app by generating a configuration
-and pushing it to ONOS.  **If you are not setting up the single-node development POD**, you will 
-need to modify the generated configuration via the XOS GUI. (The defaults
-should be OK for the single-node POD.)  For more information
-about how to configure VTN, see [the CORD VTN page on the ONOS Wiki](https://wiki.onosproject.org/display/ONOS/CORD+VTN),
-under the **ONOS Settings** heading.   
+and pushing it to ONOS.  You are able to see and modify the configuration
+via the GUI as follows:
 
 * To see the generated configuration, go to *http://xos/admin/onos/onosapp/*, select
 *VTN_ONOS_app*, then the *Attributes* tab, and look for the
 `rest_onos/v1/network/configuration/` attribute.  
 
-* To change `privateGatewayMac`, `localManagementIp`, `ovsdbPort`, `sshPort`, 
-`sshUser` or `sshKeyFile` in the generated configuration, select *Services* at 
-left in the XOS GUI, then *service_vtn*.  Modify these fields under *VTN Service Details*
-and then select *Save*.
-
-* To change `bridgeId`, `dataPlaneIntf`, or `dataPlaneIp` for a particular compute node, go to
-*http://xos/admin/core/node/*, select a node, then select the *Tags* tab.  Modify the appropriate tag
-and then select *Save*.
+* To change the VTN configuration, modify the fields of the VTN Service object
+and the Tag objects associated with Nodes.  Don't forget to select *Save*.
 
 * After modifying the above fields, delete the `rest_onos/v1/network/configuration/` attribute
 in the *ONOS_VTN_app* and select *Save*.  The attribute will be regenerated using the new information.
 
-* Alternatively, if you want to load your own VTN configuration manually, you can delete the 
-`autogenerate` attribute from the *ONOS_VTN_app*, paste your configuration in the 
+* Alternatively, if you want to load your own VTN configuration manually, you can delete the
+`autogenerate` attribute from the *ONOS_VTN_app*, edit the configuration in the
 `rest_onos/v1/network/configuration/` attribute, and select *Save*.
 
 Before proceeding, check that the VTN app is controlling Open vSwitch on the compute nodes.  Log
@@ -135,12 +135,14 @@
 hostname=nova-compute, hostMgmtIp=192.168.122.177/24, dpIp=192.168.199.1/24, br-int=of:0000000000000001, dpIntf=veth1, init=COMPLETE
 Total 1 nodes
 ```
-The important part is the `init=COMPLETE` at the end.  If you do not see this, refer to 
+The important part is the `init=COMPLETE` at the end.  If you do not see this, refer to
 [the CORD VTN page on the ONOS Wiki](https://wiki.onosproject.org/display/ONOS/CORD+VTN) for
 help fixing the problem.  This must be working to bring up VMs on the POD.
 
-Finally modify `cord-vtn-vsg.yml` and change `addresses_vsg` so that it contains the IP address block,
-gateway IP, and gateway MAC of the fabric.  (Again, the defaults are fine for the single-node POD.)
+> If you are **not** building the single-node development POD, modify `cord-vtn-vsg.yml` 
+> and change `addresses_vsg` so that it contains the IP address block,
+> gateway IP, and gateway MAC of the CORD fabric.  
+
 Then run:
 
 ```
diff --git a/xos/configurations/cord-pod/make-vtn-external-yaml.sh b/xos/configurations/cord-pod/make-vtn-external-yaml.sh
new file mode 100644
index 0000000..c623394
--- /dev/null
+++ b/xos/configurations/cord-pod/make-vtn-external-yaml.sh
@@ -0,0 +1,107 @@
+FN=$SETUPDIR/vtn-external.yaml
+
+rm -f $FN
+
+cat >> $FN <<EOF
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+imports:
+   - custom_types/xos.yaml
+
+description: autogenerated node tags file for VTN configuration
+
+topology_template:
+  node_templates:
+
+    service_ONOS_CORD:
+      type: tosca.nodes.ONOSService
+      requirements:
+      properties:
+          kind: onos
+          view_url: /admin/onos/onosservice/$id$/
+          no_container: true
+          rest_hostname: onos-cord
+
+    service_vtn:
+      type: tosca.nodes.VTNService
+      properties:
+          view_url: /admin/vtn/vtnservice/$id$/
+          privateGatewayMac: 00:00:00:00:00:01
+          localManagementIp: 172.27.0.1/24
+          ovsdbPort: 6641
+          sshUser: root
+          sshKeyFile: /root/node_key
+          sshPort: 22
+          xosEndpoint: http://xos/
+          xosUser: padmin@vicci.org
+          xosPassword: letmein
+
+EOF
+
+NODES=$( bash -c "source $SETUPDIR/admin-openrc.sh ; nova host-list" |grep compute|awk '{print $2}' )
+I=0
+for NODE in $NODES; do
+    echo $NODE
+    cat >> $FN <<EOF
+    $NODE:
+      type: tosca.nodes.Node
+
+    # VTN bridgeId field for node $NODE
+    ${NODE}_bridgeId_tag:
+      type: tosca.nodes.Tag
+      properties:
+          name: bridgeId
+          value: of:0000000000000001
+      requirements:
+          - target:
+              node: $NODE
+              relationship: tosca.relationships.TagsObject
+          - service:
+              node: service_ONOS_CORD
+              relationship: tosca.relationships.MemberOfService
+
+    # VTN dataPlaneIntf field for node $NODE
+    ${NODE}_dataPlaneIntf_tag:
+      type: tosca.nodes.Tag
+      properties:
+          name: dataPlaneIntf
+          value: veth1
+      requirements:
+          - target:
+              node: $NODE
+              relationship: tosca.relationships.TagsObject
+          - service:
+              node: service_ONOS_CORD
+              relationship: tosca.relationships.MemberOfService
+
+    # VTN dataPlaneIp field for node $NODE
+    ${NODE}_dataPlaneIp_tag:
+      type: tosca.nodes.Tag
+      properties:
+          name: dataPlaneIp
+          value: 10.168.0.253/24
+      requirements:
+          - target:
+              node: $NODE
+              relationship: tosca.relationships.TagsObject
+          - service:
+              node: service_ONOS_CORD
+              relationship: tosca.relationships.MemberOfService
+
+EOF
+done
+
+cat >> $FN <<EOF
+    VTN_ONOS_app:
+      type: tosca.nodes.ONOSVTNApp
+      requirements:
+          - onos_tenant:
+              node: service_ONOS_CORD
+              relationship: tosca.relationships.TenantOfService
+          - vtn_service:
+              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
+          autogenerate: vtn-network-cfg
+EOF
\ No newline at end of file
diff --git a/xos/configurations/cord-pod/vtn-external.yaml b/xos/configurations/cord-pod/vtn-external.yaml
deleted file mode 100644
index 51cca08..0000000
--- a/xos/configurations/cord-pod/vtn-external.yaml
+++ /dev/null
@@ -1,36 +0,0 @@
-tosca_definitions_version: tosca_simple_yaml_1_0
-
-description: Set up ONOS VTN app
-
-imports:
-   - custom_types/xos.yaml
-
-topology_template:
-  node_templates:
-
-    service_ONOS_CORD:
-      type: tosca.nodes.ONOSService
-      requirements:
-      properties:
-          kind: onos
-          view_url: /admin/onos/onosservice/$id$/
-          no_container: true
-          rest_hostname: onos-cord
-
-    VTN_ONOS_app:
-      type: tosca.nodes.ONOSVTNApp
-      requirements:
-          - onos_tenant:
-              node: service_ONOS_CORD
-              relationship: tosca.relationships.TenantOfService
-          - vtn_service:
-              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
-          autogenerate: vtn-network-cfg
-
-    service_vtn:
-      type: tosca.nodes.VTNService
-      properties:
-          view_url: /admin/vtn/vtnservice/$id$/
diff --git a/xos/core/xoslib/methods/vtn.py b/xos/core/xoslib/methods/vtn.py
index 1a2af53..c9dbf3a 100644
--- a/xos/core/xoslib/methods/vtn.py
+++ b/xos/core/xoslib/methods/vtn.py
@@ -57,7 +57,8 @@
         for xos_service in Service.objects.all():
             if service in xos_service.get_vtn_src_ids():
                 return Response(xos_service.get_vtn_dependencies_ids())
-        raise DoesNotExist()
+        return Response([])
+        # raise DoesNotExist()
 
     def list(self, request):
         raise Exception("Not Implemented")
diff --git a/xos/services/vtn/admin.py b/xos/services/vtn/admin.py
index c64e054..c2c542d 100644
--- a/xos/services/vtn/admin.py
+++ b/xos/services/vtn/admin.py
@@ -29,6 +29,9 @@
     sshUser = forms.CharField(required=False)
     sshKeyFile = forms.CharField(required=False)
     mgmtSubnetBits = forms.CharField(required=False)
+    xosEndpoint = forms.CharField(required=False)
+    xosUser = forms.CharField(required=False)
+    xosPassword = forms.CharField(required=False)
 
     def __init__(self,*args,**kwargs):
         super (VTNServiceForm,self ).__init__(*args,**kwargs)
@@ -40,6 +43,9 @@
             self.fields['sshUser'].initial = self.instance.sshUser
             self.fields['sshKeyFile'].initial = self.instance.sshKeyFile
             self.fields['mgmtSubnetBits'].initial = self.instance.mgmtSubnetBits
+            self.fields['xosEndpoint'].initial = self.instance.xosEndpoint
+            self.fields['xosUser'].initial = self.instance.xosUser
+            self.fields['xosPassword'].initial = self.instance.xosPassword
 
     def save(self, commit=True):
         self.instance.privateGatewayMac = self.cleaned_data.get("privateGatewayMac")
@@ -49,6 +55,9 @@
         self.instance.sshUser = self.cleaned_data.get("sshUser")
         self.instance.sshKeyFile = self.cleaned_data.get("sshKeyFile")
         self.instance.mgmtSubnetBits = self.cleaned_data.get("mgmtSubnetBits")
+        self.instance.mgmtSubnetBits = self.cleaned_data.get("xosEndpoint")
+        self.instance.mgmtSubnetBits = self.cleaned_data.get("xosUser")
+        self.instance.mgmtSubnetBits = self.cleaned_data.get("xosPassword")
         return super(VTNServiceForm, self).save(commit=commit)
 
     class Meta:
@@ -62,7 +71,7 @@
     list_display = ("backend_status_icon", "name", "enabled")
     list_display_links = ('backend_status_icon', 'name', )
     fieldsets = [(None, {'fields': ['backend_status_text', 'name','enabled','versionNumber','description',"view_url","icon_url",
-                                    'privateGatewayMac', 'localManagementIp', 'ovsdbPort', 'sshPort', 'sshUser', 'sshKeyFile', 'mgmtSubnetBits' ], 'classes':['suit-tab suit-tab-general']})]
+                                    'privateGatewayMac', 'localManagementIp', 'ovsdbPort', 'sshPort', 'sshUser', 'sshKeyFile', 'mgmtSubnetBits', 'xosEndpoint', 'xosUser', 'xosPassword' ], 'classes':['suit-tab suit-tab-general']})]
     readonly_fields = ('backend_status_text', )
     inlines = [SliceInline,ServiceAttrAsTabInline,ServicePrivilegeInline]
 
@@ -84,4 +93,3 @@
         return VTNService.get_service_objects_by_user(request.user)
 
 admin.site.register(VTNService, VTNServiceAdmin)
-
diff --git a/xos/services/vtn/models.py b/xos/services/vtn/models.py
index cb254d7..52b1633 100644
--- a/xos/services/vtn/models.py
+++ b/xos/services/vtn/models.py
@@ -37,8 +37,10 @@
                           ("sshUser", "root"),
                           ("sshKeyFile", "/root/node_key") ,
                           ("mgmtSubnetBits", "24"),
+                          ("xosEndpoint", "http://xos/"),
+                          ("xosUser", "padmin@vicci.org"),
+                          ("xosPassword", "letmein"),
 
                          )
 
 VTNService.setup_simple_attributes()
-
diff --git a/xos/synchronizers/onos/steps/sync_onosapp.py b/xos/synchronizers/onos/steps/sync_onosapp.py
index 1233ad7..7b80641 100644
--- a/xos/synchronizers/onos/steps/sync_onosapp.py
+++ b/xos/synchronizers/onos/steps/sync_onosapp.py
@@ -118,18 +118,9 @@
                 raise Exception("Controller user object for %s does not exist" % instance.creator)
             return cuser.kuser_id
 
-
-    def node_tag_default(self, o, node, tagname, default):
+    def get_node_tag(self, o, node, tagname):
         tags = Tag.select_by_content_object(node).filter(name=tagname)
-        if tags:
-            value = tags[0].value
-        else:
-            value = default
-            logger.info("node %s: saving default value %s for tag %s" % (node.name, value, tagname))
-            service = self.get_onos_service(o)
-            tag = Tag(service=service, content_object=node, name=tagname, value=value)
-            tag.save()
-        return value
+        return tags[0].value
 
     # Scan attrs for attribute name
     # If it's not present, save it as a TenantAttribute
@@ -153,6 +144,9 @@
         sshUser = None
         sshKeyFile = None
         mgmtSubnetBits = None
+        xosEndpoint = None
+        xosUser = None
+        xosPassword = None
 
         # VTN-specific configuration from the VTN Service
         vtns = VTNService.get_service_objects().all()
@@ -165,6 +159,9 @@
             sshUser = vtn.sshUser
             sshKeyFile = vtn.sshKeyFile
             mgmtSubnetBits = vtn.mgmtSubnetBits
+            xosEndpoint = vtn.xosEndpoint
+            xosUser = vtn.xosUser
+            xosPassword = vtn.xosPassword
 
         # OpenStack endpoints and credentials
         keystone_server = "http://keystone:5000/v2.0/"
@@ -196,6 +193,11 @@
                             "user": user_name,
                             "password": password
                         },
+                        "xos": {
+                            "endpoint": xosEndpoint,
+                            "user": xosUser,
+                            "password": xosPassword
+                        },
                         "publicGateways": [],
                         "nodes" : []
                     }
@@ -209,10 +211,9 @@
             nodeip = socket.gethostbyname(node.name)
 
             try:
-                bridgeId = self.node_tag_default(o, node, "bridgeId", "of:0000000000000001")
-                dataPlaneIntf = self.node_tag_default(o, node, "dataPlaneIntf", "veth1")
-                # This should be generated from the AddressPool if not present
-                dataPlaneIp = self.node_tag_default(o, node, "dataPlaneIp", "192.168.199.1/24")
+                bridgeId = self.get_node_tag(o, node, "bridgeId")
+                dataPlaneIntf = self.get_node_tag(o, node, "dataPlaneIntf")
+                dataPlaneIp = self.get_node_tag(o, node, "dataPlaneIp")
             except:
                 logger.error("not adding node %s to the VTN configuration" % node.name)
                 continue
diff --git a/xos/tosca/custom_types/xos.m4 b/xos/tosca/custom_types/xos.m4
index 783f0d4..32eefa4 100644
--- a/xos/tosca/custom_types/xos.m4
+++ b/xos/tosca/custom_types/xos.m4
@@ -282,6 +282,16 @@
             mgmtSubnetBits:
                 type: string
                 required: false
+            xosEndpoint:
+                type: string
+                required: false
+            xosUser:
+                type: string
+                required: false
+            xosPassword:
+                type: string
+                required: false
+
 
     tosca.nodes.CDNService:
         derived_from: tosca.nodes.Root
diff --git a/xos/tosca/custom_types/xos.yaml b/xos/tosca/custom_types/xos.yaml
index 1450a5e..8102d1c 100644
--- a/xos/tosca/custom_types/xos.yaml
+++ b/xos/tosca/custom_types/xos.yaml
@@ -516,6 +516,15 @@
             mgmtSubnetBits:
                 type: string
                 required: false
+            xosEndpoint:
+                type: string
+                required: false
+            xosUser:
+                type: string
+                required: false
+            xosPassword:
+                type: string
+                required: false
 
     tosca.nodes.CDNService:
         derived_from: tosca.nodes.Root
diff --git a/xos/tosca/resources/vtnservice.py b/xos/tosca/resources/vtnservice.py
index f0940d6..2a5738f 100644
--- a/xos/tosca/resources/vtnservice.py
+++ b/xos/tosca/resources/vtnservice.py
@@ -12,5 +12,4 @@
 class XOSVTNService(XOSService):
     provides = "tosca.nodes.VTNService"
     xos_model = VTNService
-    copyin_props = ["view_url", "icon_url", "enabled", "published", "public_key", "versionNumber", 'privateGatewayMac', 'localManagementIp', 'ovsdbPort', 'sshPort', 'sshUser', 'sshKeyFile', 'mgmtSubnetBits']
-
+    copyin_props = ["view_url", "icon_url", "enabled", "published", "public_key", "versionNumber", 'privateGatewayMac', 'localManagementIp', 'ovsdbPort', 'sshPort', 'sshUser', 'sshKeyFile', 'mgmtSubnetBits', 'xosEndpoint', 'xosUser', 'xosPassword']