Preliminary support for P4 switches

Change-Id: I2665813772bc5334eb171d9b304c3a80fff4d536
diff --git a/VERSION b/VERSION
index 7dd050c..276cbf9 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.2.3-dev
+2.3.0
diff --git a/xos/synchronizer/migrations/0007_switch_pipeconf.py b/xos/synchronizer/migrations/0007_switch_pipeconf.py
new file mode 100644
index 0000000..2ef3a7b
--- /dev/null
+++ b/xos/synchronizer/migrations/0007_switch_pipeconf.py
@@ -0,0 +1,34 @@
+# 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.
+
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.23 on 2019-08-05 17:10
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('fabric', '0006_auto_20190416_1711'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='switch',
+            name='pipeconf',
+            field=models.CharField(blank=True, help_text=b'Pipeline configuration', max_length=1024, null=True),
+        ),
+    ]
diff --git a/xos/synchronizer/models/fabric.xproto b/xos/synchronizer/models/fabric.xproto
index d717d94..d7023bd 100644
--- a/xos/synchronizer/models/fabric.xproto
+++ b/xos/synchronizer/models/fabric.xproto
@@ -40,6 +40,9 @@
         help_text = "Address where this switch can be managed",
         feedback_state = True,
         max_length = 1024];
+    optional string pipeconf = 9 [
+        help_text = "Pipeline configuration",
+        max_length = 1024];
 }
 
 message SwitchPort(XOSBase) {
diff --git a/xos/synchronizer/steps/sync_fabric_switch.py b/xos/synchronizer/steps/sync_fabric_switch.py
index cac7ac5..15031cf 100644
--- a/xos/synchronizer/steps/sync_fabric_switch.py
+++ b/xos/synchronizer/steps/sync_fabric_switch.py
@@ -40,7 +40,9 @@
                 model.ofId: {
                     "basic": {
                         "name": model.name,
-                        "driver": model.driver
+                        "driver": model.driver,
+                        "pipeconf": model.pipeconf,
+                        "managementAddress": model.managementAddress
                     },
                     "segmentrouting": {
                         "name": model.name,
@@ -48,7 +50,7 @@
                         "ipv4Loopback": model.ipv4Loopback,
                         "routerMac": model.routerMac,
                         "isEdgeRouter": model.isEdgeRouter,
-                        "adjacencySids": []
+                        "adjacencySids": [],
                     }
                 }
             }
@@ -61,7 +63,7 @@
 
         if r.status_code != 200:
             log.error(r.text)
-            raise Exception("Failed to add device %s into ONOS" % model.name)
+            raise Exception("Failed to add device %s into ONOS: %s" % (model.name, r.text))
         else:
             try:
                 log.info("result", json=r.json())
diff --git a/xos/synchronizer/steps/test_sync_fabric_switch.py b/xos/synchronizer/steps/test_sync_fabric_switch.py
index b749b94..f9facea 100644
--- a/xos/synchronizer/steps/test_sync_fabric_switch.py
+++ b/xos/synchronizer/steps/test_sync_fabric_switch.py
@@ -101,13 +101,17 @@
         self.o.ipv4Loopback = "192.168.0.201"
         self.o.routerMac = "00:00:02:01:06:01"
         self.o.isEdgeRouter = False
+        self.o.pipeconf = "pipeconf"
+        self.o.managementAddress = "192.168.100.123"
 
         expected_conf = {
             "devices": {
                 self.o.ofId: {
                     "basic": {
                         "name": self.o.name,
-                        "driver": self.o.driver
+                        "driver": self.o.driver,
+                        "pipeconf": self.o.pipeconf,
+                        "managementAddress": self.o.managementAddress
                     },
                     "segmentrouting": {
                         "name": self.o.name,