SEBA-497 delayering, Makefile, and tox for onos-synchronizer

Change-Id: I849b307330a6fd5a5de5489d8f2db804a02acead
diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..b8f06bb
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,2 @@
+.tox
+venv-service
diff --git a/.gitignore b/.gitignore
index 0f03cd1..0d57996 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,8 +1,7 @@
 .idea
-*.pyc
-
+.tox
 .coverage
-htmlcov
 coverage.xml
-nose2-junit.xml
-
+nose2-results.xml
+venv-service
+*.pyc
diff --git a/Dockerfile.synchronizer b/Dockerfile.synchronizer
index 0b24cbf..8340881 100644
--- a/Dockerfile.synchronizer
+++ b/Dockerfile.synchronizer
@@ -16,7 +16,15 @@
 
 # xosproject/onos-synchronizer
 
-FROM xosproject/xos-synchronizer-base:2.2.18
+FROM xosproject/alpine-grpc-base:0.9.0
+
+# Install pip packages
+COPY requirements.txt /tmp/requirements.txt
+RUN pip install -r /tmp/requirements.txt \
+ && pip freeze > /var/xos/pip_freeze_onos_service_`date -u +%Y%m%dT%H%M%S`
+ 
+
+# Copy files
 COPY xos/synchronizer /opt/xos/synchronizers/onos
 COPY VERSION /opt/xos/synchronizers/onos/
 
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..c29b928
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,80 @@
+# Copyright 2019-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.
+
+# Configure shell
+SHELL = bash -e -o pipefail
+
+# Variables
+VERSION                  ?= $(shell cat ./VERSION)
+SERVICE_NAME             ?= $(notdir $(abspath .))
+SYNCHRONIZER_NAME        ?= onos-synchronizer
+
+## Docker related
+DOCKER_REGISTRY          ?=
+DOCKER_REPOSITORY        ?=
+DOCKER_BUILD_ARGS        ?=
+DOCKER_TAG               ?= ${VERSION}
+DOCKER_IMAGENAME         := ${DOCKER_REGISTRY}${DOCKER_REPOSITORY}${SYNCHRONIZER_NAME}:${DOCKER_TAG}
+
+## Docker labels. Only set ref and commit date if committed
+DOCKER_LABEL_VCS_URL     ?= $(shell git remote get-url $(shell git remote))
+DOCKER_LABEL_VCS_REF     ?= $(shell git diff-index --quiet HEAD -- && git rev-parse HEAD || echo "unknown")
+DOCKER_LABEL_COMMIT_DATE ?= $(shell git diff-index --quiet HEAD -- && git show -s --format=%cd --date=iso-strict HEAD || echo "unknown" )
+DOCKER_LABEL_BUILD_DATE  ?= $(shell date -u "+%Y-%m-%dT%H:%M:%SZ")
+
+## Migration related - paths are relative to the xos subdirectory within this repo
+XOS_DIR                  ?= "../../../xos"
+SERVICES_DIR             ?= "../.."
+
+all: test
+
+docker-build:
+	docker build $(DOCKER_BUILD_ARGS) \
+    -t ${DOCKER_IMAGENAME} \
+    --build-arg org_label_schema_version="${VERSION}" \
+    --build-arg org_label_schema_vcs_url="${DOCKER_LABEL_VCS_URL}" \
+    --build-arg org_label_schema_vcs_ref="${DOCKER_LABEL_VCS_REF}" \
+    --build-arg org_label_schema_build_date="${DOCKER_LABEL_BUILD_DATE}" \
+    --build-arg org_opencord_vcs_commit_date="${DOCKER_LABEL_COMMIT_DATE}" \
+    -f Dockerfile.synchronizer .
+
+docker-push:
+	docker push ${DOCKER_IMAGENAME}
+
+test: test-unit test-migration
+
+test-unit:
+	tox
+
+venv-service:
+	virtualenv $@;\
+    source ./$@/bin/activate ; set -u ;\
+    pip install -r requirements.txt xosmigrate~=3.0.1
+
+create-migration: venv-service
+	source ./venv-service/bin/activate; set -u;\
+    cd xos; xos-migrate --xos-dir ${XOS_DIR} --services-dir ${SERVICES_DIR} -s ${SERVICE_NAME}
+
+test-migration: venv-service
+	source ./venv-service/bin/activate; set -u;\
+    cd xos; xos-migrate --xos-dir ${XOS_DIR} --services-dir ${SERVICES_DIR} -s ${SERVICE_NAME} --check
+
+clean:
+	find . -name '*.pyc' | xargs rm -f
+	rm -rf \
+    .tox \
+    venv-service \
+    xos/.coverage \
+    xos/coverage.xml \
+    xos/nose2-results.xml
diff --git a/VERSION b/VERSION
index 82bd22f..7ec1d6d 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.0.13
+2.1.0
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..e039eea
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,3 @@
+xossynchronizer~=3.0.1
+xosapi~=3.0.1
+xoskafka~=3.0.1
diff --git a/tox.ini b/tox.ini
new file mode 100644
index 0000000..9064a11
--- /dev/null
+++ b/tox.ini
@@ -0,0 +1,46 @@
+; Copyright 2019-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.
+
+[tox]
+envlist = py27
+; future; envlist = py27,py35,py36,py37
+skip_missing_interpreters = true
+skipsdist = True
+
+[testenv]
+deps =
+  -r requirements.txt
+  requests_mock
+  nose2
+;  flake8
+
+changedir = xos
+commands =
+  nose2 -c ../tox.ini --verbose --junit-xml
+; future: flake8
+
+[flake8]
+max-line-length = 119
+
+[unittest]
+plugins = nose2.plugins.junitxml
+
+[junit-xml]
+path = nose2-results.xml
+
+[coverage]
+always-on = True
+coverage-report =
+  term
+  xml
diff --git a/xos/synchronizer/__init__.py b/xos/synchronizer/__init__.py
new file mode 100644
index 0000000..19d1424
--- /dev/null
+++ b/xos/synchronizer/__init__.py
@@ -0,0 +1,13 @@
+# Copyright 2019-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.
diff --git a/xos/synchronizer/event_steps/__init__.py b/xos/synchronizer/event_steps/__init__.py
new file mode 100644
index 0000000..19d1424
--- /dev/null
+++ b/xos/synchronizer/event_steps/__init__.py
@@ -0,0 +1,13 @@
+# Copyright 2019-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.
diff --git a/xos/synchronizer/event_steps/kubernetes_event.py b/xos/synchronizer/event_steps/kubernetes_event.py
index 67c2569..d319eb0 100644
--- a/xos/synchronizer/event_steps/kubernetes_event.py
+++ b/xos/synchronizer/event_steps/kubernetes_event.py
@@ -15,8 +15,6 @@
 
 
 import json
-import os
-import sys
 from xossynchronizer.event_steps.eventstep import EventStep
 from xossynchronizer.modelaccessor import ONOSApp, ONOSService
 from xosconfig import Config
@@ -24,6 +22,7 @@
 
 log = create_logger(Config().get('logging'))
 
+
 class KubernetesPodDetailsEventStep(EventStep):
     topics = ["xos.kubernetes.pod-details"]
     technology = "kafka"
@@ -52,18 +51,23 @@
                 continue
 
             log.info("Dirtying ONOS Service", service=service)
-            service.backend_code=0
-            service.backend_status="resynchronize due to kubernetes event"
+            service.backend_code = 0
+            service.backend_status = "resynchronize due to kubernetes event"
             service.save(update_fields=["updated", "backend_code", "backend_status"], always_update_timestamp=True)
 
             for app in service.service_instances.all():
                 log.info("Dirtying ONOS App", app=app)
-                app.backend_code=0
-                app.backend_status="resynchronize due to kubernetes event"
+                app.backend_code = 0
+                app.backend_status = "resynchronize due to kubernetes event"
                 app.save(update_fields=["updated", "backend_code", "backend_status"], always_update_timestamp=True)
 
                 for attr in app.service_instance_attributes.all():
                     log.info("Dirtying ServiceInstanceAttributes for App", app=app, attr=attr)
                     attr.backend_code = 0
                     attr.backend_status = "resynchronize due to kubernetes event"
-                    attr.save(update_fields=["updated", "backend_code", "backend_status"], always_update_timestamp=True)
+                    attr.save(
+                        update_fields=[
+                            "updated",
+                            "backend_code",
+                            "backend_status"],
+                        always_update_timestamp=True)
diff --git a/xos/synchronizer/event_steps/test_kubernetes_event.py b/xos/synchronizer/event_steps/test_kubernetes_event.py
index 3d81f78..70d20df 100644
--- a/xos/synchronizer/event_steps/test_kubernetes_event.py
+++ b/xos/synchronizer/event_steps/test_kubernetes_event.py
@@ -14,13 +14,12 @@
 
 import unittest
 import json
-import functools
-from mock import patch, call, Mock, PropertyMock
-import requests_mock
+from mock import patch, call, Mock
 
-import os, sys
+import os
+import sys
 
-test_path=os.path.abspath(os.path.dirname(os.path.realpath(__file__)))
+test_path = os.path.abspath(os.path.dirname(os.path.realpath(__file__)))
 
 
 class TestKubernetesEvent(unittest.TestCase):
@@ -38,15 +37,13 @@
         # END Setting up the config module
 
         from xossynchronizer.mock_modelaccessor_build import mock_modelaccessor_config
-        mock_modelaccessor_config(test_path, [("onos-service", "onos.xproto"),])
+        mock_modelaccessor_config(test_path, [("onos-service", "onos.xproto"), ])
 
         import xossynchronizer.modelaccessor
         import mock_modelaccessor
-        reload(mock_modelaccessor) # in case nose2 loaded it in a previous test
+        reload(mock_modelaccessor)  # in case nose2 loaded it in a previous test
         reload(xossynchronizer.modelaccessor)      # in case nose2 loaded it in a previous test
 
-        from kubernetes_event import KubernetesPodDetailsEventStep
-
         from xossynchronizer.modelaccessor import model_accessor
 
         self.model_accessor = model_accessor
@@ -62,10 +59,10 @@
         self.event_step = KubernetesPodDetailsEventStep
 
         self.onos = ONOSService(name="myonos",
-                                rest_hostname = "onos-url",
-                                rest_port = "8181",
-                                rest_username = "karaf",
-                                rest_password = "karaf",
+                                rest_hostname="onos-url",
+                                rest_port="8181",
+                                rest_username="karaf",
+                                rest_password="karaf",
                                 backend_code=1,
                                 backend_status="succeeded")
 
@@ -78,16 +75,16 @@
         self.mockAllAttr.all.return_value = [self.attr]
 
         self.app1 = ONOSApp(name="myapp1",
-                           owner=self.onos,
-                           backend_code=1,
-                           backend_status="succeeded",
-                           service_instance_attributes=self.mockAllAttr)
+                            owner=self.onos,
+                            backend_code=1,
+                            backend_status="succeeded",
+                            service_instance_attributes=self.mockAllAttr)
 
         self.app2 = ONOSApp(name="myapp2",
-                           owner=self.onos,
-                           backend_code=1,
-                           backend_status="succeeded",
-                           service_instance_attributes=self.mockAllAttr)
+                            owner=self.onos,
+                            backend_code=1,
+                            backend_status="succeeded",
+                            service_instance_attributes=self.mockAllAttr)
 
         self.onos.service_instances = MockObjectList([self.app1, self.app2])
 
@@ -99,9 +96,9 @@
 
     def test_process_event(self):
         with patch.object(ONOSService.objects, "get_items") as service_objects, \
-             patch.object(ONOSService, "save", autospec=True) as service_save, \
-             patch.object(ONOSApp, "save", autospec=True) as app_save, \
-             patch.object(ServiceInstanceAttribute, "save", autospec=True) as attr_save:
+                patch.object(ONOSService, "save", autospec=True) as service_save, \
+                patch.object(ONOSApp, "save", autospec=True) as app_save, \
+                patch.object(ServiceInstanceAttribute, "save", autospec=True) as attr_save:
             service_objects.return_value = [self.onos]
 
             event_dict = {"status": "created",
@@ -114,8 +111,13 @@
 
             self.assertEqual(self.onos.backend_code, 0)
             self.assertEqual(self.onos.backend_status, "resynchronize due to kubernetes event")
-            service_save.assert_called_with(self=self.onos, update_fields=["updated", "backend_code", "backend_status"],
-                                            always_update_timestamp=True)
+            service_save.assert_called_with(
+                self=self.onos,
+                update_fields=[
+                    "updated",
+                    "backend_code",
+                    "backend_status"],
+                always_update_timestamp=True)
 
             self.assertEqual(self.app1.backend_code, 0)
             self.assertEqual(self.app1.backend_status, "resynchronize due to kubernetes event")
@@ -206,9 +208,5 @@
             self.assertEqual(self.app2.backend_status, "succeeded")
 
 
-
 if __name__ == '__main__':
     unittest.main()
-
-
-
diff --git a/xos/synchronizer/models/models.py b/xos/synchronizer/models/models.py
index e4e1948..2e962bb 100644
--- a/xos/synchronizer/models/models.py
+++ b/xos/synchronizer/models/models.py
@@ -17,6 +17,7 @@
 from models_decl import ONOSApp_decl
 from models_decl import ONOSService_decl
 
+
 class ONOSApp(ONOSApp_decl):
     class Meta:
         proxy = True
@@ -24,12 +25,13 @@
     def save(self, *args, **kwargs):
 
         if self.url and not self.version:
-            raise XOSValidationError("If you specify a url, you also need to specify a version. ONOSApp:  %s" % self.name)
+            raise XOSValidationError(
+                "If you specify a url, you also need to specify a version. ONOSApp:  %s" %
+                self.name)
 
         super(ONOSApp, self).save(*args, **kwargs)
 
 
 class ONOSService(ONOSService_decl):
-   class Meta:
-        proxy = True 
-
+    class Meta:
+        proxy = True
diff --git a/xos/synchronizer/steps/__init__.py b/xos/synchronizer/steps/__init__.py
new file mode 100644
index 0000000..19d1424
--- /dev/null
+++ b/xos/synchronizer/steps/__init__.py
@@ -0,0 +1,13 @@
+# Copyright 2019-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.
diff --git a/xos/synchronizer/steps/helpers.py b/xos/synchronizer/steps/helpers.py
index 9d5f197..2629638 100644
--- a/xos/synchronizer/steps/helpers.py
+++ b/xos/synchronizer/steps/helpers.py
@@ -14,6 +14,7 @@
 
 from xossynchronizer.modelaccessor import Service
 
+
 class Helpers():
     @staticmethod
     def format_url(url):
diff --git a/xos/synchronizer/steps/sync_onos_app.py b/xos/synchronizer/steps/sync_onos_app.py
index d9b0f4c..210f8ce 100644
--- a/xos/synchronizer/steps/sync_onos_app.py
+++ b/xos/synchronizer/steps/sync_onos_app.py
@@ -27,6 +27,7 @@
 log = create_logger(Config().get('logging'))
 log.info("config file", file=Config().get_config_file())
 
+
 class SyncONOSApp(SyncStep):
     provides = [ONOSApp]
     observes = [ONOSApp, ServiceInstanceAttribute]
@@ -44,21 +45,25 @@
         """
         if not deps:
             return True
-        for dep in [x.strip() for x in deps.split(',') if x is not ""]:
+        for dep in [x.strip() for x in deps.split(',') if x != ""]:
             try:
                 app = ONOSApp.objects.get(app_id=dep)
                 if not app.backend_code == 1:
                     # backend_code == 1 means that the app has been pushed
                     return False
-            except IndexError, e:
+            except IndexError:
                 return False
         return True
 
     def add_config(self, o):
         log.info("Adding config %s" % o.name, model=o.tologdict())
         # getting onos url and auth
-        onos_url = "%s:%s" % (Helpers.format_url(o.service_instance.leaf_model.owner.leaf_model.rest_hostname), o.service_instance.leaf_model.owner.leaf_model.rest_port)
-        onos_basic_auth = HTTPBasicAuth(o.service_instance.leaf_model.owner.leaf_model.rest_username, o.service_instance.leaf_model.owner.leaf_model.rest_password)
+        onos_url = "%s:%s" % (Helpers.format_url(
+            o.service_instance.leaf_model.owner.leaf_model.rest_hostname),
+            o.service_instance.leaf_model.owner.leaf_model.rest_port)
+        onos_basic_auth = HTTPBasicAuth(
+            o.service_instance.leaf_model.owner.leaf_model.rest_username,
+            o.service_instance.leaf_model.owner.leaf_model.rest_password)
 
         # push configs (if any)
         url = o.name
@@ -145,10 +150,14 @@
 
         if request.status_code != 200:
             log.error("Request failed", response=request.text)
-            raise Exception("Failed to read application %s from ONOS: %s while checking correct version" % (url, request.text))
+            raise Exception(
+                "Failed to read application %s from ONOS: %s while checking correct version" %
+                (url, request.text))
         else:
             if o.version != request.json()["version"]:
-                raise Exception("The version of %s you installed (%s) is not the same you requested (%s)" % (o.app_id, request.json()["version"], o.version))
+                raise Exception(
+                    "The version of %s you installed (%s) is not the same you requested (%s)" %
+                    (o.app_id, request.json()["version"], o.version))
 
     def sync_record(self, o):
         log.info("Sync'ing", model=o.tologdict())
@@ -156,7 +165,7 @@
             # this is a ServiceInstanceAttribute model just push the config
             if 'ONOSApp' in o.service_instance.leaf_model.class_names:
                 return self.add_config(o)
-            return # if it's not an ONOSApp do nothing
+            return  # if it's not an ONOSApp do nothing
 
         if not self.check_app_dependencies(o.dependencies):
             raise DeferredException('Deferring installation of ONOSApp with id %s as dependencies are not met' % o.id)
@@ -176,8 +185,12 @@
         log.info("Deleting config %s" % o.name)
         # getting onos url and auth
         onos_app = o.service_instance.leaf_model
-        onos_url = "%s:%s" % (Helpers.format_url(onos_app.owner.leaf_model.rest_hostname), onos_app.owner.leaf_model.rest_port)
-        onos_basic_auth = HTTPBasicAuth(onos_app.owner.leaf_model.rest_username, onos_app.owner.leaf_model.rest_password)
+        onos_url = "%s:%s" % (Helpers.format_url(
+            onos_app.owner.leaf_model.rest_hostname),
+            onos_app.owner.leaf_model.rest_port)
+        onos_basic_auth = HTTPBasicAuth(
+            onos_app.owner.leaf_model.rest_username,
+            onos_app.owner.leaf_model.rest_password)
 
         url = o.name
         if url[0] == "/":
@@ -191,7 +204,7 @@
             log.error("Request failed", response=request.text)
             raise Exception("Failed to remove config %s from ONOS:  %s" % (url, request.text))
 
-    def uninstall_app(self,o, onos_url, onos_basic_auth):
+    def uninstall_app(self, o, onos_url, onos_basic_auth):
         log.info("Uninstalling app %s" % o.app_id)
         url = '%s/onos/v1/applications/%s' % (onos_url, o.app_id)
 
@@ -217,7 +230,7 @@
             # this is a ServiceInstanceAttribute model
             if 'ONOSApp' in o.service_instance.leaf_model.class_names:
                 return self.delete_config(o)
-            return # if it's not related to an ONOSApp do nothing
+            return  # if it's not related to an ONOSApp do nothing
 
         # NOTE if it is an ONOSApp we don't care about the ServiceInstanceAttribute
         # as the reaper will delete it
diff --git a/xos/synchronizer/steps/sync_onos_service.py b/xos/synchronizer/steps/sync_onos_service.py
index 8f1550a..fae13e7 100644
--- a/xos/synchronizer/steps/sync_onos_service.py
+++ b/xos/synchronizer/steps/sync_onos_service.py
@@ -26,6 +26,7 @@
 
 log = create_logger(Config().get('logging'))
 
+
 class SyncONOSService(SyncStep):
     provides = [ONOSService]
     observes = [ONOSService, ServiceAttribute]
@@ -41,7 +42,7 @@
             if 'ONOSService' in o.service.leaf_model.class_names:
                 print "sync ONOSService Attribute", o.service.leaf_model
                 return self.sync_record(o.service.leaf_model)
-            return # if it's not related to an ONOSService do nothing
+            return  # if it's not related to an ONOSService do nothing
 
         onos_url = "%s:%s" % (Helpers.format_url(o.rest_hostname), o.rest_port)
         onos_basic_auth = HTTPBasicAuth(o.rest_username, o.rest_password)
@@ -72,7 +73,7 @@
                 # getting onos url and auth
                 onos_service = o.service.leaf_model
                 onos_url = "%s:%s" % (
-                Helpers.format_url(onos_service.rest_hostname), onos_service.rest_port)
+                    Helpers.format_url(onos_service.rest_hostname), onos_service.rest_port)
                 onos_basic_auth = HTTPBasicAuth(onos_service.rest_username,
                                                 onos_service.rest_password)
 
diff --git a/xos/synchronizer/steps/test_sync_onos_app.py b/xos/synchronizer/steps/test_sync_onos_app.py
index fb38a50..4dffeec 100644
--- a/xos/synchronizer/steps/test_sync_onos_app.py
+++ b/xos/synchronizer/steps/test_sync_onos_app.py
@@ -13,25 +13,27 @@
 # limitations under the License.
 
 import unittest
-import json
 import functools
-from mock import patch, call, Mock, PropertyMock
+from mock import patch, Mock
 import requests_mock
 
-import os, sys
+import os
+import sys
 
-test_path=os.path.abspath(os.path.dirname(os.path.realpath(__file__)))
+test_path = os.path.abspath(os.path.dirname(os.path.realpath(__file__)))
 
 
 def match_none(req):
-    return req.text == None
+    return req.text is None
+
 
 def match_json(desired, req):
-    if desired!=req.json():
+    if desired != req.json():
         raise Exception("Got request %s, but body is not matching" % req.url)
         return False
     return True
 
+
 class TestSyncOnosApp(unittest.TestCase):
 
     def setUp(self):
@@ -47,11 +49,11 @@
         # END Setting up the config module
 
         from xossynchronizer.mock_modelaccessor_build import mock_modelaccessor_config
-        mock_modelaccessor_config(test_path, [("onos-service", "onos.xproto"),])
+        mock_modelaccessor_config(test_path, [("onos-service", "onos.xproto"), ])
 
         import xossynchronizer.modelaccessor
         import mock_modelaccessor
-        reload(mock_modelaccessor) # in case nose2 loaded it in a previous test
+        reload(mock_modelaccessor)  # in case nose2 loaded it in a previous test
         reload(xossynchronizer.modelaccessor)      # in case nose2 loaded it in a previous test
 
         from sync_onos_app import SyncONOSApp, DeferredException, model_accessor
@@ -62,7 +64,6 @@
         for (k, v) in model_accessor.all_model_classes.items():
             globals()[k] = v
 
-
         self.sync_step = SyncONOSApp
 
         onos = ONOSService()
@@ -110,8 +111,8 @@
         self.onos_app_attribute.service_instance = self.si
         self.onos_app_attribute.name = "/onos/v1/network/configuration/apps/org.opencord.olt"
         self.onos_app_attribute.value = {
-            "kafka" : {
-                "bootstrapServers" : "cord-kafka-kafka.default.svc.cluster.local:9092"
+            "kafka": {
+                "bootstrapServers": "cord-kafka-kafka.default.svc.cluster.local:9092"
             }
         }
 
@@ -132,14 +133,16 @@
         openflow.backend_code = 0
 
         with patch.object(ONOSApp.objects, "get_items") as app_get, \
-            patch.object(ServiceInstance.objects, "get_items") as mock_si, \
-            self.assertRaises(DeferredException) as e:
+                patch.object(ServiceInstance.objects, "get_items") as mock_si, \
+                self.assertRaises(DeferredException) as e:
 
             app_get.return_value = [segment_routing, openflow]
             mock_si.return_value = [self.si]
             self.sync_step(model_accessor=self.model_accessor).sync_record(self.onos_app)
 
-        self.assertEqual(e.exception.message, 'Deferring installation of ONOSApp with id 1 as dependencies are not met')
+        self.assertEqual(
+            e.exception.message,
+            'Deferring installation of ONOSApp with id 1 as dependencies are not met')
         self.assertFalse(m.called)
 
     @requests_mock.Mocker()
@@ -153,8 +156,8 @@
                additional_matcher=match_none)
 
         m.get("http://onos-url:8181/onos/v1/applications/org.onosproject.vrouter",
-               status_code=200,
-               json=self.vrouter_app_response)
+              status_code=200,
+              json=self.vrouter_app_response)
 
         self.si.serviceinstanceattribute_dict = {}
 
@@ -177,8 +180,8 @@
                additional_matcher=match_none)
 
         m.get("http://onos-url:8181/onos/v1/applications/org.onosproject.vrouter",
-               status_code=200,
-               json=self.vrouter_app_response)
+              status_code=200,
+              json=self.vrouter_app_response)
 
         self.si.serviceinstanceattribute_dict = {}
 
@@ -260,13 +263,12 @@
                additional_matcher=functools.partial(match_json, expected),
                json=self.vrouter_app_response)
 
-
         m.get("http://onos-url:8181/onos/v1/applications/org.onosproject.vrouter",
               [
                   {"json": self.vrouter_app_response, "status_code": 200},
                   {"json": self.vrouter_app_response_updated, "status_code": 200}
               ]
-        )
+              )
 
         m.delete("http://onos-url:8181/onos/v1/applications/org.onosproject.vrouter",
                  status_code=204)
@@ -308,19 +310,22 @@
         self.si.serviceinstanceattribute_dict = {}
 
         with patch.object(ServiceInstance.objects, "get_items") as mock_si, \
-            self.assertRaises(Exception) as e:
+                self.assertRaises(Exception) as e:
             mock_si.return_value = [self.si]
             self.sync_step(model_accessor=self.model_accessor).sync_record(self.onos_app)
 
         self.assertTrue(m.called)
         self.assertEqual(m.call_count, 3)
         self.assertEqual(self.onos_app.app_id, self.vrouter_app_response["name"])
-        self.assertEqual(e.exception.message, "The version of org.onosproject.vrouter you installed (1.13.1) is not the same you requested (1.14.2)")
+        self.assertEqual(
+            e.exception.message,
+            "The version of org.onosproject.vrouter you installed (1.13.1) is not the same you requested (1.14.2)")
 
     @requests_mock.Mocker()
     def test_handle_409(self, m):
         """
-        A 409 "Application Already installed" response is not an error. This should not happen as we check if the app is installed.
+        A 409 "Application Already installed" response is not an error. This should not happen as we check
+        if the app is installed.
         """
 
         self.onos_app.url = 'http://onf.org/maven/...'
@@ -342,7 +347,7 @@
     @requests_mock.Mocker()
     def test_config_delete(self, m):
         m.delete("http://onos-url:8181%s" % self.onos_app_attribute.name,
-               status_code=204)
+                 status_code=204)
 
         self.sync_step(model_accessor=self.model_accessor).delete_record(self.onos_app_attribute)
         self.assertTrue(m.called)
@@ -351,7 +356,7 @@
     @requests_mock.Mocker()
     def test_app_deactivate(self, m):
         m.delete("http://onos-url:8181/onos/v1/applications/org.onosproject.vrouter/active",
-               status_code=204)
+                 status_code=204)
 
         self.sync_step(model_accessor=self.model_accessor).delete_record(self.onos_app)
         self.assertTrue(m.called)
@@ -370,6 +375,6 @@
         self.assertTrue(m.called)
         self.assertEqual(m.call_count, 1)
 
+
 if __name__ == '__main__':
     unittest.main()
-
diff --git a/xos/synchronizer/steps/test_sync_onos_service.py b/xos/synchronizer/steps/test_sync_onos_service.py
index ee6daaf..054baea 100644
--- a/xos/synchronizer/steps/test_sync_onos_service.py
+++ b/xos/synchronizer/steps/test_sync_onos_service.py
@@ -15,20 +15,22 @@
 import unittest
 import json
 import functools
-from mock import patch, call, Mock, PropertyMock
+from mock import patch, Mock
 import requests_mock
 
-import os, sys
+import os
+import sys
 
-test_path=os.path.abspath(os.path.dirname(os.path.realpath(__file__)))
+test_path = os.path.abspath(os.path.dirname(os.path.realpath(__file__)))
 
 
 def match_json(desired, req):
-    if desired!=req.json():
+    if desired != req.json():
         raise Exception("Got request %s, but body is not matching" % req.url)
         return False
     return True
 
+
 class TestSyncOnosService(unittest.TestCase):
 
     def setUp(self):
@@ -43,11 +45,11 @@
         # END Setting up the config module
 
         from xossynchronizer.mock_modelaccessor_build import mock_modelaccessor_config
-        mock_modelaccessor_config(test_path, [("onos-service", "onos.xproto"),])
+        mock_modelaccessor_config(test_path, [("onos-service", "onos.xproto"), ])
 
         import xossynchronizer.modelaccessor
         import mock_modelaccessor
-        reload(mock_modelaccessor) # in case nose2 loaded it in a previous test
+        reload(mock_modelaccessor)  # in case nose2 loaded it in a previous test
         reload(xossynchronizer.modelaccessor)      # in case nose2 loaded it in a previous test
 
         from sync_onos_service import SyncONOSService, model_accessor
@@ -58,7 +60,6 @@
         for (k, v) in model_accessor.all_model_classes.items():
             globals()[k] = v
 
-
         self.sync_step = SyncONOSService
 
         self.onos = Mock(spec=[
@@ -162,14 +163,16 @@
                additional_matcher=functools.partial(match_json, json.loads(expected_conf)))
 
         with self.assertRaises(Exception) as e, \
-            patch.object(Service.objects, "get_items") as service_mock:
+                patch.object(Service.objects, "get_items") as service_mock:
 
             service_mock.return_value = [self.service]
             self.sync_step(model_accessor=self.model_accessor).sync_record(self.onos)
 
         self.assertTrue(m.called)
         self.assertEqual(m.call_count, 1)
-        self.assertEqual(e.exception.message, "Failed to add config http://onos-url:8181/onos/v1/network/configuration/apps/org.onosproject.olt in ONOS")
+        self.assertEqual(
+            e.exception.message,
+            "Failed to add config http://onos-url:8181/onos/v1/network/configuration/apps/org.onosproject.olt in ONOS")
 
     @requests_mock.Mocker()
     def test_delete(self, m):
@@ -180,5 +183,6 @@
         self.assertTrue(m.called)
         self.assertEqual(m.call_count, 1)
 
+
 if __name__ == '__main__':
     unittest.main()
diff --git a/xos/unittest.cfg b/xos/unittest.cfg
deleted file mode 100644
index 882a030..0000000
--- a/xos/unittest.cfg
+++ /dev/null
@@ -1,12 +0,0 @@
-[unittest]
-plugins=nose2.plugins.junitxml
-code-directories=synchronizer
-                 steps
-		 event_steps
-
-[coverage]
-always-on = True
-coverage = synchronizer
-coverage-report = term
-coverage-report = html
-coverage-report = xml