Merge branch 'master' of github.com:open-cloud/xos
diff --git a/xos/tosca/custom_types/xos.yaml b/xos/tosca/custom_types/xos.yaml
index 440c0d2..ebe1e05 100644
--- a/xos/tosca/custom_types/xos.yaml
+++ b/xos/tosca/custom_types/xos.yaml
@@ -15,6 +15,54 @@
 #                default: false
 #                description: prevent this resource from being deleted
 
+    tosca.nodes.NetworkTemplate:
+        derived_from: tosca.nodes.Root
+
+        capabilities:
+            network_template:
+                type: tosca.capabilities.xos.NetworkTemplate
+
+        properties:
+            visibility:
+                type: string
+                default: private
+            translation:
+                type: string
+                default: none
+            shared_network_name:
+                type: string
+                required: false
+            shared_network_id:
+                type: string
+                required: false
+            topology_kind:
+                type: string
+                default: BigSwitch
+            controller_kind:
+                type: string
+                required: false
+
+    tosca.nodes.XOSNetwork:
+        derived_from: tosca.nodes.Root
+
+        capabilities:
+            network:
+                type: tosca.capabilities.xos.Network
+
+        properties:
+            ports:
+                type: string
+                required: false
+            labels:
+                type: string
+                required: false
+            permit_all_slices:
+                type: boolean
+                default: false
+            permitted_slices:
+                type: string
+                required: false
+
     tosca.nodes.Deployment:
         derived_from: tosca.nodes.Root
         capabilities:
@@ -110,6 +158,18 @@
         derived_from: tosca.relationships.Root
         valid_target_types: [ tosca.capabilities.xos.Controller ]
 
+    tosca.relationships.ConnectsToNetwork:
+        derived_from: tosca.relationships.Root
+        valid_target_types: [ tosca.capabilitys.xos.Network ]
+
+#    tosca.relationships.OwnsNetwork:
+#        derived_from: tosca.relationships.Root
+#        valid_target_types: [ tosca.capabilitys.xos.Network ]
+
+    tosca.relationships.UsesNetworkTemplate:
+        derived_from: tosca.relationships.Root
+        valid_target_types: [ tosca.capabilitys.xos.NetworkTemplate ]
+
     tosca.capabilities.xos.Service:
         derived_from: tosca.capabilities.Root
         description: An XOS Service
@@ -129,3 +189,11 @@
     tosca.capabilities.xos.Slice:
         derived_from: tosca.capabilities.Root
         description: An XOS Slice
+
+    tosca.capabilities.xos.NetworkTemplate:
+        derived_from: tosca.capabilities.Root
+        description: An XOS network template
+
+    tosca.capabilities.xos.Network:
+        derived_from: tosca.capabilities.Root
+        description: An XOS network
diff --git a/xos/tosca/engine.py b/xos/tosca/engine.py
index efe64e2..5417cbc 100644
--- a/xos/tosca/engine.py
+++ b/xos/tosca/engine.py
@@ -121,7 +121,7 @@
     def execute_nodetemplate(self, user, nodetemplate):
         if nodetemplate.type in resources.resources:
             cls = resources.resources[nodetemplate.type]
-            print "work on", cls.__name__, nodetemplate.name
+            #print "work on", cls.__name__, nodetemplate.name
             obj = cls(user, nodetemplate)
             obj.create_or_update()
 
diff --git a/xos/tosca/resources/network.py b/xos/tosca/resources/network.py
new file mode 100644
index 0000000..d8a93f8
--- /dev/null
+++ b/xos/tosca/resources/network.py
@@ -0,0 +1,66 @@
+import os
+import pdb
+import sys
+import tempfile
+sys.path.append("/opt/tosca")
+from translator.toscalib.tosca_template import ToscaTemplate
+
+from core.models import Slice,User,Network,NetworkTemplate
+
+from xosresource import XOSResource
+
+class XOSNetwork(XOSResource):
+    provides = "tosca.nodes.XOSNetwork"
+    xos_model = Network
+
+    def get_xos_args(self):
+        args = {"name": self.nodetemplate.name}
+
+        slice_name = self.get_requirement("tosca.relationships.MemberOfSlice")
+        if slice_name:
+            args["owner"] = self.get_xos_object(Slice, name=slice_name)
+
+        net_template_name = self.get_requirement("tosca.relationships.UsesNetworkTemplate")
+        if net_template_name:
+            args["template"] = self.get_xos_object(NetworkTemplate, name=net_template_name)
+
+        # copy simple string properties from the template into the arguments
+        for prop in ["ports", "labels", "permit_all_slices"]:
+            v = self.get_property(prop)
+            if v:
+                args[prop] = v
+
+        return args
+
+    def postprocess(self, obj):
+        v = self.get_property("permitted_slices")
+        if v:
+            for slicename in v.split(","):
+                slice = self.get_xos_object(Slice, name = slicename.strip())
+
+                if not obj.permitted_slices.filter(id = slice.id).exists():
+                    obj.permitted_slices.add(slice)
+
+    def create(self):
+        nodetemplate = self.nodetemplate
+
+        xos_args = self.get_xos_args()
+
+        if not xos_args.get("owner", None):
+            raise Exception("Must specify slice when creating network")
+        if not xos_args.get("template", None):
+            raise Exception("Must specify network template when creating network")
+
+        network = Network(**xos_args)
+        network.caller = self.user
+        network.save()
+
+        self.postprocess(network)
+
+        self.info("Created Network '%s' owned by Slice '%s'" % (str(network), str(network.owner)))
+
+    def delete(self, obj):
+        super(XOSNetwork, self).delete(obj)
+
+
+
diff --git a/xos/tosca/resources/networktemplate.py b/xos/tosca/resources/networktemplate.py
new file mode 100644
index 0000000..927c65a
--- /dev/null
+++ b/xos/tosca/resources/networktemplate.py
@@ -0,0 +1,45 @@
+import os
+import pdb
+import sys
+import tempfile
+sys.path.append("/opt/tosca")
+from translator.toscalib.tosca_template import ToscaTemplate
+
+from core.models import Slice,User,Network,NetworkTemplate
+
+from xosresource import XOSResource
+
+class XOSNetworkTemplate(XOSResource):
+    provides = "tosca.nodes.NetworkTemplate"
+    xos_model = NetworkTemplate
+
+    def get_xos_args(self):
+        args = {"name": self.nodetemplate.name}
+
+        # copy simple string properties from the template into the arguments
+        for prop in ["visibility", "translation", "shared_network_name", "shared_network_id", "toplogy_kind", "controller_kind"]:
+            v = self.get_property(prop)
+            if v:
+                args[prop] = v
+
+        return args
+
+    def create(self):
+        nodetemplate = self.nodetemplate
+
+        xos_args = self.get_xos_args()
+
+        networkTemplate = NetworkTemplate(**xos_args)
+        networkTemplate.caller = self.user
+        networkTemplate.save()
+
+        self.info("Created NetworkTemplate '%s' " % (str(networkTemplate), ))
+
+    def delete(self, obj):
+        if obj.network_set.exists():
+            return
+
+        super(XOSNetworkTemplate, self).delete(obj)
+
+
+
diff --git a/xos/tosca/resources/slice.py b/xos/tosca/resources/slice.py
index 7ac45f7..054111c 100644
--- a/xos/tosca/resources/slice.py
+++ b/xos/tosca/resources/slice.py
@@ -5,7 +5,7 @@
 sys.path.append("/opt/tosca")
 from translator.toscalib.tosca_template import ToscaTemplate
 
-from core.models import Slice,User,Site
+from core.models import Slice,User,Site,Network,NetworkSlice
 
 from xosresource import XOSResource
 
@@ -19,6 +19,14 @@
         return {"name": self.nodetemplate.name,
                 "site": site}
 
+    def postprocess(self, obj):
+        for net_name in self.get_requirements("tosca.relationships.ConnectsToNetwork"):
+            net = self.get_xos_object(Network, name=net_name)
+            if not NetworkSlice.objects.filter(network=net, slice=obj):
+                ns = NetworkSlice(network=net, slice=obj)
+                ns.save()
+                self.info("Added network connection from '%s' to '%s'" % (str(obj), str(net)))
+
     def create(self):
         nodetemplate = self.nodetemplate
         sliceName = nodetemplate.name
@@ -28,6 +36,8 @@
         slice.caller = self.user
         slice.save()
 
+        self.postprocess(slice)
+
         self.info("Created Slice '%s' on Site '%s'" % (str(slice), str(slice.site)))
 
     def delete(self, obj):
diff --git a/xos/tosca/samples/network_templates.yaml b/xos/tosca/samples/network_templates.yaml
new file mode 100644
index 0000000..5941079
--- /dev/null
+++ b/xos/tosca/samples/network_templates.yaml
@@ -0,0 +1,22 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: Make some network templates
+
+imports:
+   - custom_types/xos.yaml
+
+topology_template:
+  node_templates:
+    template1:
+      type: tosca.nodes.NetworkTemplate
+
+    template2:
+      type: tosca.nodes.NetworkTemplate
+      properties:
+          visibility: public
+          translation: NAT
+          shared_network_name: two
+          shared_network_id: 2222
+          topology_kind: bigswitch
+          controller_kind: onos
+
diff --git a/xos/tosca/samples/two_slices_shared_private_net.yaml b/xos/tosca/samples/two_slices_shared_private_net.yaml
new file mode 100644
index 0000000..203144d
--- /dev/null
+++ b/xos/tosca/samples/two_slices_shared_private_net.yaml
@@ -0,0 +1,92 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: Template for deploying a single server with predefined properties.
+
+imports:
+   - custom_types/xos.yaml
+
+topology_template:
+  node_templates:
+    mysite:
+      type: tosca.nodes.Site
+
+    Private:
+      type: tosca.nodes.NetworkTemplate
+
+    producer_private_network:
+      type: tosca.nodes.XOSNetwork
+      requirements:
+          - network_template:
+              node: Private
+              relationship: tosca.relationships.UsesNetworkTemplate
+          - slice:
+              node: mysite_producer
+              relationship: tosca.relationships.MemberOfSlice
+      properties:
+          permit_all_slices: true
+          # TODO: We can't use permitted_slices due to a cycle in the dependency
+          #       graph. Slices connect to networks, but networks have slices
+          #       in whitelists. Oops.
+          #permitted_slices: mysite_consumer
+
+    mysite_producer:
+      type: tosca.nodes.Slice
+      requirements:
+          - slice:
+                node: mysite
+                relationship: tosca.relationships.MemberOfSite
+
+    mysite_consumer:
+      type: tosca.nodes.Slice
+      requirements:
+          - slice:
+                node: mysite
+                relationship: tosca.relationships.MemberOfSite
+          - network:
+                node: producer_private_network
+                relationship: tosca.relationships.ConnectsToNetwork
+
+    producer_server:
+      type: tosca.nodes.Compute
+      capabilities:
+        # Host container properties
+        host:
+         properties:
+           num_cpus: 1
+           disk_size: 10 GB
+           mem_size: 4 MB
+        # Guest Operating System properties
+        os:
+          properties:
+            # host Operating System image properties
+            architecture: x86_64
+            type: linux
+            distribution: rhel
+            version: 6.5
+      requirements:
+          - slice:
+                node: mysite_producer
+                relationship: tosca.relationships.MemberOfSlice
+
+    consumer_server:
+      type: tosca.nodes.Compute
+      capabilities:
+        # Host container properties
+        host:
+         properties:
+           num_cpus: 1
+           disk_size: 10 GB
+           mem_size: 4 MB
+        # Guest Operating System properties
+        os:
+          properties:
+            # host Operating System image properties
+            architecture: x86_64
+            type: linux
+            distribution: rhel
+            version: 6.5
+      requirements:
+          - slice:
+                node: mysite_consumer
+                relationship: tosca.relationships.MemberOfSlice
+