Merge branch 'master' of https://github.com/open-cloud/xos
diff --git a/xos/scripts/opencloud b/xos/scripts/opencloud
index 6705b20..b936ce3 100755
--- a/xos/scripts/opencloud
+++ b/xos/scripts/opencloud
@@ -147,6 +147,7 @@
     python ./manage.py makemigrations syndicate_storage
     python ./manage.py makemigrations cord
     python ./manage.py makemigrations ceilometer
+    python ./manage.py makemigrations onos
     #python ./manage.py makemigrations servcomp
 }
 
diff --git a/xos/services/onos/templates/onosadmin.html b/xos/services/onos/templates/onosadmin.html
new file mode 100644
index 0000000..1e8d42c
--- /dev/null
+++ b/xos/services/onos/templates/onosadmin.html
@@ -0,0 +1,6 @@
+<div class = "left-nav">
+<ul>
+<li><a href="/admin/onos/onosapp/">ONOS Apps</a></li>
+</ul>
+</div>
+
diff --git a/xos/tosca/custom_types/xos.m4 b/xos/tosca/custom_types/xos.m4
index 00805e7..3d766f1 100644
--- a/xos/tosca/custom_types/xos.m4
+++ b/xos/tosca/custom_types/xos.m4
@@ -89,6 +89,35 @@
         properties:
             xos_base_service_props
 
+    tosca.nodes.ONOSService:
+        derived_from: tosca.nodes.Root
+        description: >
+            ONOS Service
+        capabilities:
+            xos_base_service_caps
+        properties:
+            xos_base_service_props
+
+    tosca.nodes.ONOSApp:
+        derived_from: tosca.nodes.Root
+        description: >
+            An ONOS Application.
+        properties:
+            xos_base_tenant_props
+
+    tosca.nodes.ONOSvBNGApp:
+        derived_from: tosca.nodes.Root
+        description: >
+            An ONOS Application.
+        properties:
+            xos_base_tenant_props
+            config_addresses_json:
+                type: string
+                required: false
+            config_virtualbng_json:
+                type: string
+                required: false
+
     tosca.nodes.VCPEService:
         description: >
             CORD: The vCPE Service.
diff --git a/xos/tosca/custom_types/xos.yaml b/xos/tosca/custom_types/xos.yaml
index 2a904c1..97031a6 100644
--- a/xos/tosca/custom_types/xos.yaml
+++ b/xos/tosca/custom_types/xos.yaml
@@ -57,6 +57,78 @@
                 required: false
                 description: Version number of Service.
 
+    tosca.nodes.ONOSService:
+        derived_from: tosca.nodes.Root
+        description: >
+            ONOS Service
+        capabilities:
+            scalable:
+                type: tosca.capabilities.Scalable
+            service:
+                type: tosca.capabilities.xos.Service
+        properties:
+            kind:
+                type: string
+                default: generic
+                description: Type of service.
+            view_url:
+                type: string
+                required: false
+                description: URL to follow when icon is clicked in the Service Directory.
+            icon_url:
+                type: string
+                required: false
+                description: ICON to display in the Service Directory.
+            enabled:
+                type: boolean
+                default: true
+            published:
+                type: boolean
+                default: true
+                description: If True then display this Service in the Service Directory.
+            public_key:
+                type: string
+                required: false
+                description: Public key to install into Instances to allows Services to SSH into them.
+            versionNumber:
+                type: string
+                required: false
+                description: Version number of Service.
+
+    tosca.nodes.ONOSApp:
+        derived_from: tosca.nodes.Root
+        description: >
+            An ONOS Application.
+        properties:
+            kind:
+                type: string
+                default: generic
+                description: Kind of tenant
+            service_specific_id:
+                type: string
+                required: false
+                description: Service specific ID opaque to XOS but meaningful to service
+
+    tosca.nodes.ONOSvBNGApp:
+        derived_from: tosca.nodes.Root
+        description: >
+            An ONOS Application.
+        properties:
+            kind:
+                type: string
+                default: generic
+                description: Kind of tenant
+            service_specific_id:
+                type: string
+                required: false
+                description: Service specific ID opaque to XOS but meaningful to service
+            config_addresses_json:
+                type: string
+                required: false
+            config_virtualbng_json:
+                type: string
+                required: false
+
     tosca.nodes.VCPEService:
         description: >
             CORD: The vCPE Service.
diff --git a/xos/tosca/resources/onosapp.py b/xos/tosca/resources/onosapp.py
new file mode 100644
index 0000000..50af543
--- /dev/null
+++ b/xos/tosca/resources/onosapp.py
@@ -0,0 +1,57 @@
+import os
+import pdb
+import sys
+import tempfile
+sys.path.append("/opt/tosca")
+from translator.toscalib.tosca_template import ToscaTemplate
+import pdb
+
+from core.models import User, TenantAttribute
+from services.onos.models import ONOSApp, ONOSService
+
+from xosresource import XOSResource
+
+class XOSONOSApp(XOSResource):
+    provides = ["tosca.nodes.ONOSApp", "tosca.nodes.ONOSvBNGApp"]
+    xos_model = ONOSApp
+    copyin_props = ["service_specific_id"]
+
+    def get_xos_args(self, throw_exception=True):
+        args = super(XOSONOSApp, self).get_xos_args()
+
+        provider_name = self.get_requirement("tosca.relationships.TenantOfService", throw_exception=throw_exception)
+        if provider_name:
+            args["provider_service"] = self.get_xos_object(ONOSService, throw_exception=throw_exception, name=provider_name)
+
+        return args
+
+    def get_existing_objs(self):
+        objs = ONOSApp.get_tenant_objects().all()
+        objs = [x for x in objs if x.name == self.nodetemplate.name]
+        return objs
+
+    def set_tenant_attr(self, obj, prop_name, value):
+        value = self.try_intrinsic_function(value)
+        if value:
+            attrs = TenantAttribute.objects.filter(tenant=obj, name=prop_name)
+            if attrs:
+                attr = attrs[0]
+                if attr.value != value:
+                    self.info("updating attribute %s" % k)
+                    attrs.value = value
+                    attrs.save()
+            else:
+                self.info("adding attribute %s" % prop_name)
+                ta = TenantAttribute(tenant=obj, name=prop_name, value=value)
+                ta.save()
+
+    def postprocess(self, obj):
+        props = self.nodetemplate.get_properties()
+        for (k,d) in props.items():
+            v = d.value
+            if k.startswith("config_"):
+                self.set_tenant_attr(obj, k, v)
+
+    def can_delete(self, obj):
+        return super(XOSONOSApp, self).can_delete(obj)
+
diff --git a/xos/tosca/resources/onosservice.py b/xos/tosca/resources/onosservice.py
new file mode 100644
index 0000000..1275fab
--- /dev/null
+++ b/xos/tosca/resources/onosservice.py
@@ -0,0 +1,16 @@
+import os
+import pdb
+import sys
+import tempfile
+sys.path.append("/opt/tosca")
+from translator.toscalib.tosca_template import ToscaTemplate
+
+from services.onos.models import ONOSService
+
+from service import XOSService
+
+class XOSONOSService(XOSService):
+    provides = "tosca.nodes.ONOSService"
+    xos_model = ONOSService
+    copyin_props = ["view_url", "icon_url", "enabled", "published", "public_key", "versionNumber"]
+
diff --git a/xos/tosca/samples/onos.yaml b/xos/tosca/samples/onos.yaml
new file mode 100644
index 0000000..311819e
--- /dev/null
+++ b/xos/tosca/samples/onos.yaml
@@ -0,0 +1,54 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: Setup CORD-related services -- vOLT, vCPE, vBNG.
+
+imports:
+   - custom_types/xos.yaml
+
+topology_template:
+  node_templates:
+    ONOS:
+      type: tosca.nodes.ONOSService
+      requirements:
+      properties:
+          kind: onos
+          view_url: /admin/onos/onosservice/$id$/
+
+    vBNG:
+      type: tosca.nodes.ONOSvBNGApp
+      requirements:
+          - onos_tenant:
+              node: ONOS
+              relationship: tosca.relationships.TenantOfService
+      properties:
+          config_addresses_json: >
+            {
+                "addresses" : [

+                            {

+                                "dpid" : "00:00:00:00:00:00:00:a1",

+                                "port" : "2",

+                                "ips" : ["192.0.0.1/24"],

+                                "mac" : "00:00:00:00:00:99"

+

+                            },

+                            {

+                                "dpid" : "00:00:00:00:00:00:00:a5",

+                                "port" : "4",

+                                "ips" : ["200.0.0.5/24"],

+                                "mac" : "00:00:00:00:00:98"

+                            }

+                ]

+            }
+          config_virtualbng_json: >
+            {
+                "localPublicIpPrefixes" : [

+                    "200.0.0.0/32",

+                    "201.0.0.0/30",

+                    "202.0.0.0/30"

+                ],

+                "nextHopIpAddress" : "200.0.0.5",

+                "publicFacingMac" : "00:00:00:00:00:66",

+                "xosIpAddress" : "10.11.10.1",

+                "xosRestPort" : "9999"

+            }
+