first cut at Tosca for VOLT Devices
diff --git a/xos/configurations/cord-pod/cord-volt-devices.yaml b/xos/configurations/cord-pod/cord-volt-devices.yaml
new file mode 100644
index 0000000..5068fa8
--- /dev/null
+++ b/xos/configurations/cord-pod/cord-volt-devices.yaml
@@ -0,0 +1,50 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: Just enough Tosca to get the vSG slice running on the CORD POD
+
+imports:
+   - custom_types/xos.yaml
+
+topology_template:
+  node_templates:
+    service#volt:
+      type: tosca.nodes.VOLTService
+      properties:
+          no-create: True
+          no-delete: True
+          no-update: True
+
+    voltdev-1:
+      type: tosca.nodes.VOLTDevice
+      properties:
+            driver: pmc-olt
+            openflow_id: of:1000000000000001
+      requirements:
+          - volt_service:
+              node: service#volt
+              relationship: tosca.relationships.MemberOfService
+
+    access-2-222:
+      type: tosca.nodes.AccessDevice
+      properties:
+          uplink: 2
+          vlan: 222
+      requirements:
+          - volt_device:
+              node: voltdev-1
+              relationship: tosca.relationships.MemberOfDevice
+
+    agent-1:
+      type: tosca.nodes.AccessAgent
+      properties:
+          mac: AA:BB:CC:DD:EE:FF
+          port_mappings: >
+            of:0000000000000002/2 DE:AD:BE:EF:BA:11,
+            of:0000000000000002/3 BE:EF:DE:AD:BE:EF
+      requirements:
+          - volt_service:
+              node: service#volt
+              relationship: tosca.relationships.MemberOfService
+
+
+
diff --git a/xos/tosca/resources/accessagent.py b/xos/tosca/resources/accessagent.py
new file mode 100644
index 0000000..99d576b
--- /dev/null
+++ b/xos/tosca/resources/accessagent.py
@@ -0,0 +1,49 @@
+import os
+import pdb
+import sys
+import tempfile
+sys.path.append("/opt/tosca")
+from translator.toscalib.tosca_template import ToscaTemplate
+
+from services.cord.models import AccessAgent, VOLTDevice, VOLTService, AgentPortMapping
+from xosresource import XOSResource
+
+class XOSAccessAgent(XOSResource):
+    provides = "tosca.nodes.AccessAgent"
+    xos_model = AccessAgent
+    copyin_props = ["mac"]
+
+    def get_xos_args(self, throw_exception=True):
+        args = super(XOSAccessAgent, self).get_xos_args()
+
+        volt_service_name = self.get_requirement("tosca.relationships.MemberOfService", throw_exception=throw_exception)
+        if volt_service_name:
+            args["volt_service"] = self.get_xos_object(VOLTService, throw_exception=throw_exception, name=volt_service_name)
+
+        return args
+
+    def postprocess(self, obj):
+        port_mappings_str = self.get_property("port_mappings")
+        port_mappings = []
+        if port_mappings_str:
+            lines = [x.strip() for x in port_mappings_str.split(",")]
+            for line in lines:
+                if not (" " in line):
+                    raise "Malformed port mapping `%s`", line
+                (port, mac) = line.split(" ")
+                port=port.strip()
+                mac=mac.strip()
+                port_mappings.append( (port, mac) )
+
+            for apm in list(AgentPortMapping.objects.filter(access_agent=obj)):
+                if (apm.port, apm.mac) not in port_mappings:
+                    print "Deleting AgentPortMapping '%s'" % apm
+                    apm.delete()
+
+            for port_mapping in port_mappings:
+                existing_objs = AgentPortMapping.objects.filter(access_agent=obj, port=port_mapping[0], mac=port_mapping[1])
+                if not existing_objs:
+                    apm = AgentPortMapping(access_agent=obj, port=port_mapping[0], mac=port_mapping[1])
+                    apm.save()
+                    print "Created AgentPortMapping '%s'" % apm
+
diff --git a/xos/tosca/resources/accessdevice.py b/xos/tosca/resources/accessdevice.py
new file mode 100644
index 0000000..94deb86
--- /dev/null
+++ b/xos/tosca/resources/accessdevice.py
@@ -0,0 +1,40 @@
+import os
+import pdb
+import sys
+import tempfile
+sys.path.append("/opt/tosca")
+from translator.toscalib.tosca_template import ToscaTemplate
+
+from services.cord.models import AccessDevice, VOLTDevice
+from xosresource import XOSResource
+
+class XOSAccessDevice(XOSResource):
+    provides = "tosca.nodes.AccessDevice"
+    xos_model = AccessDevice
+    copyin_props = ["uplink", "vlan"]
+    name_field = None
+
+    def get_xos_args(self, throw_exception=True):
+        args = super(XOSAccessDevice, self).get_xos_args()
+
+        volt_device_name = self.get_requirement("tosca.relationships.MemberOfDevice", throw_exception=throw_exception)
+        if volt_device_name:
+            args["volt_device"] = self.get_xos_object(VOLTDevice, throw_exception=throw_exception, name=volt_device_name)
+
+        return args
+
+    # AccessDevice has no name field, so we rely on matching the keys. We assume
+    # the for a given VOLTDevice, there is only one AccessDevice per (uplink, vlan)
+    # pair.
+
+    def get_existing_objs(self):
+        args = self.get_xos_args(throw_exception=False)
+        volt_device = args.get("volt_device", None)
+        uplink = args.get("uplink", None)
+        vlan = args.get("vlan", None)
+        if (volt_device is not None) and (uplink is not None) and (vlan is not None):
+            existing_obj = self.get_xos_object(AccessDevice, volt_device=volt_device, uplink=uplink, vlan=vlan, throw_exception=False)
+            if existing_obj:
+                return [ existing_obj ]
+        return []
+
diff --git a/xos/tosca/resources/voltdevice.py b/xos/tosca/resources/voltdevice.py
new file mode 100644
index 0000000..20978cc
--- /dev/null
+++ b/xos/tosca/resources/voltdevice.py
@@ -0,0 +1,23 @@
+import os
+import pdb
+import sys
+import tempfile
+sys.path.append("/opt/tosca")
+from translator.toscalib.tosca_template import ToscaTemplate
+
+from services.cord.models import VOLTDevice, VOLTService
+from xosresource import XOSResource
+
+class XOSVOLTDevice(XOSResource):
+    provides = "tosca.nodes.VOLTDevice"
+    xos_model = VOLTDevice
+    copyin_props = ["openflow_id", "driver"]
+
+    def get_xos_args(self, throw_exception=True):
+        args = super(XOSVOLTDevice, self).get_xos_args()
+
+        volt_service_name = self.get_requirement("tosca.relationships.MemberOfService", throw_exception=throw_exception)
+        if volt_service_name:
+            args["volt_service"] = self.get_xos_object(VOLTService, throw_exception=throw_exception, name=volt_service_name)
+
+        return args