[CORD-2962] Refactoring vrouter and adding support for static routes

Change-Id: Ie2719ca94296559caee4a1e433631cbd43019bf9
diff --git a/Dockerfile.synchronizer b/Dockerfile.synchronizer
index 378cc09..3585653 100644
--- a/Dockerfile.synchronizer
+++ b/Dockerfile.synchronizer
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# docker build -t xosproject/volt-synchronizer:candidate -f Dockerfile.synchronizer .
 
 # xosproject/vrouter-synchronizer
 FROM xosproject/xos-synchronizer-base:candidate
diff --git a/README.md b/README.md
index 1a0bdf2..e231cd3 100644
--- a/README.md
+++ b/README.md
@@ -1,168 +1,7 @@
 # VRouter sample configuration via TOSCA
 
-The VRouter service can be configured via TOSCA using a similar recipe to define `devices, ports, interfaces and ips`:
-```
-service#vrouter:
-      type: tosca.nodes.VRouterService
-      properties:
-          view_url: /admin/vrouter/
-          no-delete: true
-          no-create: true
-          rest_hostname: onos-fabric
-          rest_port: 8181
-          rest_user: onos
-          rest_pass: rocks
-    
-    device#of:00000000000000b1:
-      type: tosca.nodes.VRouterDevice
-      properties:
-        openflow_id: of:00000000000000b1
-        driver: softrouter
-        # config_key: basic
-      requirements:
-        - service#vrouter:
-            node: service#vrouter
-            relationship: tosca.relationships.MemberOfService
+The repository contains the synchronizers to configure the ONOS vRouter component.
 
-    # Port 1
-    port#port1/1:
-      type: tosca.nodes.VRouterPort
-      properties:
-        openflow_id: of:00000000000000b1/1
-      requirements:
-        - device#of:00000000000000b1:
-            node: device#of:00000000000000b1
-            relationship: tosca.relationships.PortOfDevice
-        - service#vrouter:
-            node: service#vrouter
-            relationship: tosca.relationships.MemberOfService
+The code assumes that the vRouter service depends on the fabric service, which depends on the ONOS service.
 
-    interface#b1-1:
-      type: tosca.nodes.VRouterInterface
-      properties:
-        name: b1-1
-        mac: 00:00:00:00:00:01
-      requirements:
-        - port#port1/1:
-            node: port#port1/1
-            relationship: tosca.relationships.InterfaceOfPort
-
-    ips#10.0.1.2/24:
-      type: tosca.nodes.VRouterIp
-      properties:
-        ip: 10.0.1.2/24
-      requirements:
-        - interface#b1-1:
-            node: interface#b1-1
-            relationship: tosca.relationships.IpOfInterface
-
-    # Port 2
-    port#port1/2:
-      type: tosca.nodes.VRouterPort
-      properties:
-        openflow_id: of:00000000000000b1/2
-      requirements:
-        - device#of:00000000000000b1:
-            node: device#of:00000000000000b1
-            relationship: tosca.relationships.PortOfDevice
-        - service#vrouter:
-            node: service#vrouter
-            relationship: tosca.relationships.MemberOfService
-
-    interface#b1-2:
-      type: tosca.nodes.VRouterInterface
-      properties:
-        name: b1-2
-        mac: 00:00:00:00:00:01
-      requirements:
-        - port#port1/2:
-            node: port#port1/2
-            relationship: tosca.relationships.InterfaceOfPort
-
-    ips#10.0.2.2/24:
-      type: tosca.nodes.VRouterIp
-      properties:
-        ip: 10.0.2.2/24
-      requirements:
-        - interface#b1-1:
-            node: interface#b1-2
-            relationship: tosca.relationships.IpOfInterface
-
-    # Port 3
-    port#port1/3:
-      type: tosca.nodes.VRouterPort
-      properties:
-        openflow_id: of:00000000000000b1/3
-      requirements:
-        - device#of:00000000000000b1:
-            node: device#of:00000000000000b1
-            relationship: tosca.relationships.PortOfDevice
-        - service#vrouter:
-            node: service#vrouter
-            relationship: tosca.relationships.MemberOfService
-
-    interface#b1-3:
-      type: tosca.nodes.VRouterInterface
-      properties:
-        name: b1-3
-        mac: 00:00:00:00:00:01
-      requirements:
-        - port#port1/3:
-            node: port#port1/3
-            relationship: tosca.relationships.InterfaceOfPort
-
-    ips#10.0.3.2/24:
-      type: tosca.nodes.VRouterIp
-      properties:
-        ip: 10.0.3.2/24
-      requirements:
-        - interface#b1-1:
-            node: interface#b1-3
-            relationship: tosca.relationships.IpOfInterface
-
-    # Port 4
-    port#port1/4:
-      type: tosca.nodes.VRouterPort
-      properties:
-        openflow_id: of:00000000000000b1/4
-      requirements:
-        - device#of:00000000000000b1:
-            node: device#of:00000000000000b1
-            relationship: tosca.relationships.PortOfDevice
-        - service#vrouter:
-            node: service#vrouter
-            relationship: tosca.relationships.MemberOfService
-
-    interface#b1-4:
-      type: tosca.nodes.VRouterInterface
-      properties:
-        name: b1-4
-        mac: 00:00:00:00:00:01
-        vlan: 100
-      requirements:
-        - port#port1/4:
-            node: port#port1/4
-            relationship: tosca.relationships.InterfaceOfPort
-
-    ips#10.0.4.2/24:
-      type: tosca.nodes.VRouterIp
-      properties:
-        ip: 10.0.4.2/24
-      requirements:
-        - interface#b1-1:
-            node: interface#b1-4
-            relationship: tosca.relationships.IpOfInterface
-
-    app#vrouterApp:
-      type: tosca.nodes.VRouterApp
-      properties:
-        name: org.onosproject.router
-        # can we use a relation to specify the connect point port?
-        control_plane_connect_point: of:00000000000000b1/5
-        ospf_enabled: true
-      requirements:
-          - service#vrouter:
-              node: service#vrouter
-              relationship: tosca.relationships.MemberOfService
-```
-
+For example, ONOS_Fabric -> Fabric -> vRouter
diff --git a/samples/vrouter.yaml b/samples/vrouter.yaml
new file mode 100644
index 0000000..78ccf00
--- /dev/null
+++ b/samples/vrouter.yaml
@@ -0,0 +1,38 @@
+# Copyright 2017-present Open Networking Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# curl -H "xos-username: admin@opencord.org" -H "xos-password: letmein" -X POST --data-binary @vrouter.yaml http://192.168.99.100:30007/run
+
+tosca_definitions_version: tosca_simple_yaml_1_0
+imports:
+  - custom_types/vrouterserviceinstance.yaml
+  - custom_types/vrouterstaticroute.yaml
+description: Creates a vrouter and pushes a static route
+topology_template:
+  node_templates:
+    vrouter#my_vrouter:
+      type: tosca.nodes.VRouterServiceInstance
+      properties:
+        name: my_vrouter
+
+    # Add a static route to the vRouter
+    route#my_route:
+      type: tosca.nodes.VRouterStaticRoute
+      properties:
+        prefix: "0.0.0.0/0"
+        next_hop: "192.168.0.254"
+      requirements:
+        - vrouter:
+            node: vrouter#my_vrouter
+            relationship: tosca.relationships.BelongsToOne
diff --git a/xos/synchronizer/curl_sample.md b/xos/synchronizer/curl_sample.md
deleted file mode 100644
index 4675fd8..0000000
--- a/xos/synchronizer/curl_sample.md
+++ /dev/null
@@ -1,13 +0,0 @@
-# vRouter App
-
-## Configure vRouter App in ONOS
-`curl -H "Content-Type: application/json" -X POST -d '{"controlPlaneConnectPoint":"of:001/1", "ospfEnabled": "true", "interfaces": ["b1-1"]}' --user onos:rocks http://onos-fabric:8181/onos/v1/network/configuration/apps/org.onosproject.router/router/`
-
-## Delete vRotuer App config
-`curl -X DELETE --user onos:rocks http://onos-fabric:8181/onos/v1/network/configuration/apps/org.onosproject.router/router/`
-
-## Check vRotuer App config
-`curl --user onos:rocks http://onos-fabric:8181/onos/v1/network/configuration/apps/org.onosproject.router/router/`
-
-## Add Port
-`curl --user onos:rocks -H "Content-Type: application/json" -X POST -d {"of:000000000001/1": {"interfaces": [{"ips": ["10.0.4.2/24"], "mac": "00:00:00:00:00:01", "vlan": "100", "name": "b1-1"}]}} http://onos-fabric:8181/onos/v1/network/configuration/ports/`
\ No newline at end of file
diff --git a/xos/synchronizer/model-deps b/xos/synchronizer/model-deps
index 9e26dfe..0967ef4 100644
--- a/xos/synchronizer/model-deps
+++ b/xos/synchronizer/model-deps
@@ -1 +1 @@
-{}
\ No newline at end of file
+{}
diff --git a/xos/synchronizer/models/models.py b/xos/synchronizer/models/models.py
deleted file mode 100644
index 3acc198..0000000
--- a/xos/synchronizer/models/models.py
+++ /dev/null
@@ -1,155 +0,0 @@
-
-# Copyright 2017-present Open Networking Foundation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-from django.db import models
-from core.models import Service, XOSBase, Slice, Instance, ServiceInstance, Node, Image, User, Flavor, NetworkParameter, NetworkParameterType, Port, AddressPool
-from core.models.xosbase import StrippedCharField
-import os
-from django.db import models, transaction
-from django.forms.models import model_to_dict
-from django.db.models import *
-from operator import itemgetter, attrgetter, methodcaller
-from core.models import Tag
-import traceback
-from xos.exceptions import *
-from models_decl import *
-
-
-class ConfigurationError(Exception):
-    pass
-
-
-class VRouterService (VRouterService_decl):
-    class Meta:
-        proxy = True
-
-    def ip_to_mac(self, ip):
-        (a, b, c, d) = ip.split('.')
-        return "02:42:%02x:%02x:%02x:%02x" % (int(a), int(b), int(c), int(d))
-
-    def get_gateways(self):
-        gateways = []
-        aps = self.addresspools.all()
-        for ap in aps:
-            gateways.append({"gateway_ip": ap.gateway_ip, "gateway_mac": ap.gateway_mac})
-
-        return gateways
-
-    def get_address_pool(self, name):
-        ap = AddressPool.objects.filter(name=name, service=self)
-        if not ap:
-            raise Exception("vRouter unable to find addresspool %s" % name)
-        return ap[0]
-
-    def get_tenant(self, **kwargs):
-        address_pool_name = kwargs.pop("address_pool_name")
-
-        ap = self.get_address_pool(address_pool_name)
-
-        ip = ap.get_address()
-        if not ip:
-            raise Exception("AddressPool '%s' has run out of addresses." % ap.name)
-
-        t = VRouterTenant(owner=self, **kwargs)
-        t.public_ip = ip
-        t.public_mac = self.ip_to_mac(ip)
-        t.address_pool_id = ap.id
-        t.save()
-
-        return t
-
-
-class VRouterDevice (VRouterDevice_decl):
-
-    class Meta:
-        proxy = True
-    pass
-
-class VRouterPort (VRouterPort_decl):
-
-    class Meta:
-        proxy = True
-    pass
-
-class VRouterApp (VRouterApp_decl):
-
-    class Meta:
-        proxy = True
-    def _get_interfaces(self):
-        app_interfaces = []
-        devices = VRouterDevice.objects.filter(vrouter_service=self.vrouter_service)
-        for device in devices:
-            ports = VRouterPort.objects.filter(vrouter_device=device.id)
-            for port in ports:
-                interfaces = VRouterInterface.objects.filter(vrouter_port=port.id)
-                for iface in interfaces:
-                    app_interfaces.append(iface.name)
-        return app_interfaces
-
-class VRouterInterface (VRouterInterface_decl):
-
-    class Meta:
-        proxy = True
-    pass
-
-class VRouterIp (VRouterIp_decl):
-
-    class Meta:
-        proxy = True
-    pass
-
-class VRouterTenant (VRouterTenant_decl):
-
-    class Meta:
-        proxy = True
-    @property
-    def gateway_ip(self):
-        if not self.address_pool:
-            return None
-        return self.address_pool.gateway_ip
-
-    @property
-    def gateway_mac(self):
-        if not self.address_pool:
-            return None
-        return self.address_pool.gateway_mac
-
-    @property
-    def cidr(self):
-        if not self.address_pool:
-            return None
-        return self.address_pool.cidr
-
-    @property
-    def netbits(self):
-        # return number of bits in the network portion of the cidr
-        if self.cidr:
-            parts = self.cidr.split("/")
-            if len(parts) == 2:
-                return int(parts[1].strip())
-        return None
-
-    def cleanup_addresspool(self):
-        if self.address_pool:
-            ap = self.address_pool
-            if ap:
-                ap.put_address(self.public_ip)
-                self.public_ip = None
-
-    def delete(self, *args, **kwargs):
-        self.cleanup_addresspool()
-        super(VRouterTenant, self).delete(*args, **kwargs)
-
diff --git a/xos/synchronizer/models/vrouter.xproto b/xos/synchronizer/models/vrouter.xproto
index 0a68a63..006ecb9 100644
--- a/xos/synchronizer/models/vrouter.xproto
+++ b/xos/synchronizer/models/vrouter.xproto
@@ -1,67 +1,23 @@
 option kind="vROUTER";
 option name="vrouter";
-option legacy="True";
 option app_label = "vrouter";
 
-message VRouterService (Service){
-     option verbose_name="vRouter Service";
-
-     optional string rest_hostname = 1 [db_index = False, max_length = 255, null = True, content_type = "stripped", blank = True];
-     required int32 rest_port = 2 [default = 8181, null = False, db_index = False, blank = False];
-     required string rest_user = 3 [default = "onos", max_length = 255, content_type = "stripped", blank = False, null = False, db_index = False];
-     required string rest_pass = 4 [default = "rocks", max_length = 255, content_type = "stripped", blank = False, null = False, db_index = False];
+message VRouterService (Service) {
+    option verbose_name = "vRouter Service";
 }
 
-message VRouterDevice (XOSBase){
-     option verbose_name="vRouter Device";
+message VRouterServiceInstance (ServiceInstance) {
+    option verbose_name = "vRouter Service Instance";
+    option owner_class_name = "VRouterService";
 
-     optional string name = 1 [help_text = "device friendly name", max_length = 20, null = True, db_index = False, blank = True];
-     required string openflow_id = 2 [help_text = "device identifier in ONOS", max_length = 20, null = False, db_index = False, blank = False];
-     required string config_key = 3 [default = "basic", max_length = 32, blank = False, help_text = "configuration key", null = False, db_index = False];
-     required string driver = 4 [help_text = "driver type", max_length = 32, null = False, db_index = False, blank = False];
-     required manytoone vrouter_service->VRouterService:devices = 5 [db_index = True, null = False, blank = False];
+    // TODO - to be added to select interfaces the vrouter attaches to (use _decl)
+    // required manytoone interface->PortInterface:vrouters = 1 [help_text = "The fabric port interface to which the router is connected to", db_index = False, null = False, blank = False];
 }
 
-message VRouterPort (XOSBase){
-     option verbose_name="vRouter Port";
+message VRouterStaticRoute (XOSBase) {
+    option verbose_name = "vRouter static route";
 
-     optional string name = 1 [help_text = "port friendly name", max_length = 20, null = True, db_index = False, blank = True];
-     required string openflow_id = 2 [help_text = "port identifier in ONOS", max_length = 21, null = False, db_index = False, blank = False];
-     required manytoone vrouter_device->VRouterDevice:ports = 3 [db_index = True, null = False, blank = False];
-     required manytoone vrouter_service->VRouterService:device_ports = 4 [db_index = True, null = False, blank = False];
-}
-
-message VRouterApp (XOSBase){
-     option verbose_name="vRouter App";
-
-     required manytoone vrouter_service->VRouterService:apps = 1 [db_index = True, null = False, blank = False];
-     required string name = 2 [help_text = "application name", max_length = 50, null = False, db_index = False, blank = False];
-     required string control_plane_connect_point = 3 [help_text = "port identifier in ONOS", max_length = 21, null = False, db_index = False, blank = False];
-     required bool ospf_enabled = 4 [help_text = "ospf enabled", default = True, null = False, db_index = False, blank = True];
-}
-
-message VRouterInterface (XOSBase) {
-     option verbose_name="vRouter Interface";
-
-     required manytoone vrouter_port->VRouterPort:interfaces = 1 [db_index = True, null = False, blank = False];
-     required string name = 2 [help_text = "interface name", max_length = 10, null = False, db_index = False, blank = False];
-     required string mac = 3 [help_text = "interface mac", max_length = 17, null = False, db_index = False, blank = False];
-     optional string vlan = 4 [help_text = "interface vlan id", max_length = 10, null = True, db_index = False, blank = True];
-}
-
-message VRouterIp (XOSBase){
-     option verbose_name="vRouter Ip";
-
-     optional string name = 1 [help_text = "ip friendly name", max_length = 20, null = True, db_index = False, blank = True];
-     required manytoone vrouter_interface->VRouterInterface:ips = 2 [db_index = True, null = False, blank = False];
-     required string ip = 3 [help_text = "interface ips", max_length = 19, null = False, db_index = False, blank = False];
-}
-
-message VRouterTenant (ServiceInstance){
-     option verbose_name="vRouter Tenant";
-     option owner_class_name="VRouterService";
-
-     optional string public_ip = 1 [db_index = False, max_length = 30, null = True, content_type = "stripped", blank = True];
-     optional string public_mac = 2 [db_index = False, max_length = 30, null = True, content_type = "stripped", blank = True];
-     optional manytoone address_pool->AddressPool:vrouter_tenants = 3 [db_index = True, null = True, blank = True];
+    required manytoone vrouter->VRouterServiceInstance:static_routes = 1 [help_text = "The static route to be configured in ONOS", db_index = False, null = False, blank = False];
+    required string prefix = 2 [help_text = "The destination prefix and netmask (xxx.yyy.www.zzz/nm)", max_length = 20, null = False, tosca_key = True, db_index = False, unique = True, blank = False];
+    required string next_hop = 5 [help_text = "The next-hop for the route", max_length = 17, null = False, db_index = False, blank = False];
 }
diff --git a/xos/synchronizer/steps/helpers.py b/xos/synchronizer/steps/helpers.py
new file mode 100644
index 0000000..63585aa
--- /dev/null
+++ b/xos/synchronizer/steps/helpers.py
@@ -0,0 +1,30 @@
+# Copyright 2017-present Open Networking Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+class Helpers():
+    @staticmethod
+    def format_url(url):
+        if 'http' in url:
+            return url
+        else:
+            return 'http://%s' % url
+
+    @staticmethod
+    def get_onos_info(onos_service):
+        return {
+            'url': Helpers.format_url(onos_service.rest_hostname),
+            'port': onos_service.rest_port,
+            'user': onos_service.rest_username,
+            'pass': onos_service.rest_password
+        }
diff --git a/xos/synchronizer/steps/sync_routes.py b/xos/synchronizer/steps/sync_routes.py
new file mode 100644
index 0000000..5086933
--- /dev/null
+++ b/xos/synchronizer/steps/sync_routes.py
@@ -0,0 +1,83 @@
+
+# Copyright 2017-present Open Networking Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import requests
+from requests.auth import HTTPBasicAuth
+from synchronizers.new_base.syncstep import SyncStep, DeferredException
+from synchronizers.new_base.modelaccessor import VRouterStaticRoute
+
+from helpers import Helpers
+from multistructlog import create_logger
+from xosconfig import Config
+
+log = create_logger(Config().get('logging'))
+
+class SyncRoutes(SyncStep):
+    provides = [VRouterStaticRoute]
+    observes = VRouterStaticRoute
+
+    # Get fabric service info
+    def get_onos_fabric_service(self, model):
+        vrouter_service = model.vrouter.owner
+        fabric_service = vrouter_service.subscriber_services[0]
+        onos_fabric_service = fabric_service.subscriber_services[0]
+
+        return onos_fabric_service
+
+    def sync_record(self, model):
+        onos_fabric_service = self.get_onos_fabric_service(model)
+
+        onos = Helpers.get_onos_info(onos_fabric_service.leaf_model)
+        onos_basic_auth = HTTPBasicAuth(onos['user'], onos['pass'])
+
+        data = {
+          "prefix": model.prefix,
+          "nextHop": model.next_hop
+        }
+
+        url = '%s:%s/onos/routeservice/routes' % (onos['url'], onos['port'])
+        request = requests.post(url, json=data, auth=onos_basic_auth)
+
+        if request.status_code != 204:
+            log.error("Request failed", response=request.text)
+            raise Exception("Failed to add static route %s via %s in ONOS" % (model.prefix, model.next_hop))
+        else:
+            try:
+                print request.json()
+            except Exception:
+                print request.text
+
+    def delete_record(self, model):
+        onos_fabric_service = self.get_onos_fabric_service(model)
+
+        onos = Helpers.get_onos_info(onos_fabric_service.leaf_model)
+        onos_basic_auth = HTTPBasicAuth(onos['user'], onos['pass'])
+
+        data = {
+          "prefix": model.prefix,
+          "nextHop": model.next_hop
+        }
+
+        url = '%s:%s/onos/routeservice/routes' % (onos['url'], onos['port'])
+        request = requests.delete(url, json=data, auth=onos_basic_auth)
+
+        if request.status_code != 204:
+            log.error("Request failed", response=request.text)
+            raise Exception("Failed to delete static route %s via %s in ONOS" % (model.prefix, model.next_hop))
+        else:
+            try:
+                print request.json()
+            except Exception:
+                print request.text
diff --git a/xos/synchronizer/steps/sync_vrouterapp.py b/xos/synchronizer/steps/sync_vrouterapp.py
deleted file mode 100644
index 6c83700..0000000
--- a/xos/synchronizer/steps/sync_vrouterapp.py
+++ /dev/null
@@ -1,85 +0,0 @@
-
-# Copyright 2017-present Open Networking Foundation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-import os
-import sys
-import requests
-import json
-from synchronizers.new_base.syncstep import SyncStep
-from synchronizers.new_base.modelaccessor import *
-from xos.logger import Logger, logging
-
-from requests.auth import HTTPBasicAuth
-logger = Logger(level=logging.INFO)
-
-
-class SyncVRouterApp(SyncStep):
-    provides = [VRouterApp]
-
-    observes = VRouterApp
-
-    requested_interval = 0
-
-    def __init__(self, *args, **kwargs):
-        super(SyncVRouterApp, self).__init__(*args, **kwargs)
-
-    def get_onos_fabric_addr(self, app):
-        vrouter_service = VRouterService.objects.get(id=app.vrouter_service_id)
-
-        return "http://%s:%s/onos/v1/network/configuration/" % (vrouter_service.rest_hostname, vrouter_service.rest_port)
-
-    def get_onos_fabric_auth(self, app):
-        vrouter_service = VRouterService.objects.get(id=app.vrouter_service_id)
-
-        return HTTPBasicAuth(vrouter_service.rest_user, vrouter_service.rest_pass)
-
-    def sync_record(self, app):
-
-        logger.info("Sync'ing Edited vRouterApps: %s" % app.name)
-
-        onos_addr = self.get_onos_fabric_addr(app)
-
-        data = {}
-        data["controlPlaneConnectPoint"] = app.control_plane_connect_point
-        data["ospfEnabled"] = app.ospf_enabled
-        data["interfaces"] = app.interfaces
-
-        url = onos_addr + "apps/" + app.name + "/router/"
-
-        print "POST %s for app %s" % (url, app.name)
-
-        # XXX fixme - hardcoded auth
-        auth = self.get_onos_fabric_auth(app)
-        r = requests.post(url, data=json.dumps(data), auth=auth)
-        if (r.status_code != 200):
-            print r
-            raise Exception("Received error from vrouter app update (%d)" % r.status_code)
-
-    def delete_record(self, app):
-
-        logger.info("Sync'ing Deleted vRouterApps: %s" % app.name)
-
-        onos_addr = self.get_onos_fabric_addr()
-
-        url = onos_addr + "apps/" + app.name + "/"
-
-        print "DELETE %s for app %s" % (url, app.name)
-
-        auth = self.get_onos_fabric_auth(app)
-        r = requests.delete(url, auth=auth)
-        if (r.status_code != 204):
-            print r
-            raise Exception("Received error from vrouter app deletion (%d)" % r.status_code)
\ No newline at end of file
diff --git a/xos/synchronizer/steps/sync_vrouterdevice.py b/xos/synchronizer/steps/sync_vrouterdevice.py
deleted file mode 100644
index 179ec91..0000000
--- a/xos/synchronizer/steps/sync_vrouterdevice.py
+++ /dev/null
@@ -1,82 +0,0 @@
-
-# Copyright 2017-present Open Networking Foundation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-import os
-import sys
-import requests
-import json
-from synchronizers.new_base.syncstep import SyncStep
-from synchronizers.new_base.modelaccessor import *
-from xos.logger import Logger, logging
-
-from requests.auth import HTTPBasicAuth
-logger = Logger(level=logging.INFO)
-
-
-class SyncVRouterDevice(SyncStep):
-    provides = [VRouterDevice]
-
-    observes = VRouterDevice
-
-    requested_interval = 0
-
-    def __init__(self, *args, **kwargs):
-        super(SyncVRouterDevice, self).__init__(*args, **kwargs)
-
-    def get_onos_fabric_addr(self, app):
-        vrouter_service = VRouterService.objects.get(id=app.vrouter_service_id)
-
-        return "http://%s:%s/onos/v1/network/configuration/" % (vrouter_service.rest_hostname, vrouter_service.rest_port)
-
-    def get_onos_fabric_auth(self, app):
-        vrouter_service = VRouterService.objects.get(id=app.vrouter_service_id)
-
-        return HTTPBasicAuth(vrouter_service.rest_user, vrouter_service.rest_pass)
-
-    def sync_record(self, device):
-
-        logger.info("Sync'ing Edited vRouterDevice: %s" % device.name)
-
-        onos_addr = self.get_onos_fabric_addr(device)
-
-        data = {}
-        data["driver"] = device.driver
-
-        url = onos_addr + "devices/" + device.openflow_id + "/" + device.config_key + "/"
-
-        print "POST %s for device %s" % (url, device.name)
-
-        auth = self.get_onos_fabric_auth(device)
-        r = requests.post(url, data=json.dumps(data), auth=auth)
-        if (r.status_code != 200):
-            print r
-            raise Exception("Received error from vrouter device update (%d)" % r.status_code)
-
-    def delete_record(self, device):
-
-        logger.info("Sync'ing Deleted vRouterDevice: %s" % device.name)
-
-        onos_addr = self.get_onos_fabric_addr()
-
-        url = onos_addr + "devices/" + device.openflow_id + "/"
-
-        print "DELETE %s for device %s" % (url, device.name)
-
-        auth = self.get_onos_fabric_auth(device)
-        r = requests.delete(url, auth=auth)
-        if (r.status_code != 204):
-            print r
-            raise Exception("Received error from vrouter device deletion (%d)" % r.status_code)
\ No newline at end of file
diff --git a/xos/synchronizer/steps/sync_vrouterports.py b/xos/synchronizer/steps/sync_vrouterports.py
deleted file mode 100644
index fe8eb1c..0000000
--- a/xos/synchronizer/steps/sync_vrouterports.py
+++ /dev/null
@@ -1,105 +0,0 @@
-
-# Copyright 2017-present Open Networking Foundation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-import os
-import sys
-import requests
-import json
-import urllib
-from synchronizers.new_base.syncstep import SyncStep
-from synchronizers.new_base.modelaccessor import *
-from xos.logger import Logger, logging
-
-from requests.auth import HTTPBasicAuth
-logger = Logger(level=logging.INFO)
-
-
-class SyncVRouterPort(SyncStep):
-    provides = [VRouterPort]
-
-    observes = VRouterPort
-
-    requested_interval = 0
-
-    def __init__(self, *args, **kwargs):
-        super(SyncVRouterPort, self).__init__(*args, **kwargs)
-
-    def get_onos_fabric_addr(self, app):
-        vrouter_service = VRouterService.objects.get(id=app.vrouter_service_id)
-
-        return "http://%s:%s/onos/v1/network/configuration/" % (vrouter_service.rest_hostname, vrouter_service.rest_port)
-
-    def get_onos_fabric_auth(self, app):
-        vrouter_service = VRouterService.objects.get(id=app.vrouter_service_id)
-
-        return HTTPBasicAuth(vrouter_service.rest_user, vrouter_service.rest_pass)
-
-    def sync_record(self, port):
-
-        logger.info("Sync'ing Edited vRouterPort: %s" % port.name)
-
-        # NOTE port is now related to service,
-        # probably it makes more sense to relate them to a device (and device is related to service)
-        onos_addr = self.get_onos_fabric_addr(port)
-
-        # NOTE
-        # from a port read all interfaces
-        # from interfaces read all ips
-
-        ifaces = []
-        for interface in port.interfaces.all():
-            iface = {
-                'name': interface.name,
-                'mac': interface.mac,
-                'vlan': interface.vlan,
-                'ips': []
-            }
-
-            for ip in interface.ips.all():
-                iface["ips"].append(ip.ip)
-
-            ifaces.append(iface)
-
-        data = {}
-        data[port.openflow_id] = {
-            'interfaces': ifaces
-        }
-
-        url = onos_addr + "ports/"
-
-        print "POST %s for port %s" % (url, port.name)
-
-        auth = self.get_onos_fabric_auth(port)
-        r = requests.post(url, data=json.dumps(data), auth=auth)
-        if (r.status_code != 200):
-            print r
-            raise Exception("Received error from vrouter port update (%d)" % r.status_code)
-
-    def delete_record(self, port):
-
-        logger.info("Sync'ing Deleted vRouterPort: %s" % port.name)
-
-        onos_addr = self.get_onos_fabric_addr()
-
-        url = onos_addr + "ports/" + urllib.quote(port.openflow_id, safe='') + "/"
-
-        print "DELETE %s for port %s" % (url, port.name)
-
-        auth = self.get_onos_fabric_auth(port)
-        r = requests.delete(url, auth=auth)
-        if (r.status_code != 204):
-            print r
-            raise Exception("Received error from vrouter port deletion (%d)" % r.status_code)
\ No newline at end of file
diff --git a/xos/synchronizer/vrouter-synchronizer.py b/xos/synchronizer/vrouter-synchronizer.py
index fa88098..924f008 100644
--- a/xos/synchronizer/vrouter-synchronizer.py
+++ b/xos/synchronizer/vrouter-synchronizer.py
@@ -27,8 +27,7 @@
 
 Config.init(config_file, 'synchronizer-config-schema.yaml')
 
-synchronizer_path = os.path.join(os.path.dirname(
-    os.path.realpath(__file__)), "../../synchronizers/new_base")
+synchronizer_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "../../synchronizers/new_base")
 sys.path.append(synchronizer_path)
 mod = importlib.import_module("xos-synchronizer")
 mod.main()
diff --git a/xos/synchronizer/vrouter_config.yaml b/xos/synchronizer/vrouter_config.yaml
index 7fe4f18..274ba24 100644
--- a/xos/synchronizer/vrouter_config.yaml
+++ b/xos/synchronizer/vrouter_config.yaml
@@ -20,9 +20,7 @@
   password: "@/opt/xos/services/vrouter/credentials/xosadmin@opencord.org"
 required_models:
   - VRouterService
-  - VRouterDevice
-  - VRouterApp
-  - VRouterPort
+  - VRouterServiceInstance
 dependency_graph: "/opt/xos/synchronizers/vrouter/model-deps"
 steps_dir: "/opt/xos/synchronizers/vrouter/steps"
 sys_dir: "/opt/xos/synchronizers/vrouter/sys"