add support for volumes
diff --git a/xos/configurations/frontend/Makefile b/xos/configurations/frontend/Makefile
index ce1782e..1998224 100644
--- a/xos/configurations/frontend/Makefile
+++ b/xos/configurations/frontend/Makefile
@@ -1,9 +1,11 @@
 MYIP:=$(shell hostname -i)
+CONFIG_DIR:=$(shell pwd)
 
 frontend:
 	sudo make -f ../common/Makefile.prereqs
 	sudo docker-compose up -d
 	bash ../common/wait_for_xos.sh
+	sudo docker-compose run -e CONFIG_DIR=$(CONFIG_DIR) xos python /opt/xos/tosca/run.py none /opt/xos/configurations/frontend/xos.yaml
 	sudo docker-compose run xos python /opt/xos/tosca/run.py none /opt/xos/configurations/common/fixtures.yaml
 	sudo docker-compose run xos python /opt/xos/tosca/run.py none /opt/xos/configurations/common/mydeployment.yaml
 	sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/frontend/sample.yaml
diff --git a/xos/configurations/frontend/xos.yaml b/xos/configurations/frontend/xos.yaml
new file mode 100644
index 0000000..4575de4
--- /dev/null
+++ b/xos/configurations/frontend/xos.yaml
@@ -0,0 +1,31 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: Onboard the exampleservice
+
+imports:
+   - custom_types/xos.yaml
+
+topology_template:
+  node_templates:
+    xos:
+      type: tosca.nodes.XOS
+
+    /opt/xos/xos_configuration/xos_common_config:
+      type: tosca.nodes.XOSVolume
+      properties:
+          host_path: { path_join: [ SELF, CONFIG_DIR, ../common/xos_common_config, ENV_VAR ] }
+          read_only: false
+      requirements:
+          - xos:
+             node: xos
+             relationship: tosca.relationships.UsedByXOS
+
+    /opt/xos/xos_configuration/xos_vtn_config:
+      type: tosca.nodes.XOSVolume
+      properties:
+          host_path: { path_join: [ SELF, CONFIG_DIR, ../vtn/files/xos_vtn_config, ENV_VAR ] }
+          read_only: true
+      requirements:
+          - xos:
+              node: xos
+              relationship: tosca.relationships.UsedByXOS
diff --git a/xos/core/models/__init__.py b/xos/core/models/__init__.py
index 371c73a..41e6b3b 100644
--- a/xos/core/models/__init__.py
+++ b/xos/core/models/__init__.py
@@ -1,7 +1,7 @@
 from .plcorebase import PlCoreBase,PlCoreBaseManager,PlCoreBaseDeletionManager,PlModelMixIn
 from .project import Project
 from .singletonmodel import SingletonModel
-from .xosmodel import XOS
+from .xosmodel import XOS, XOSVolume
 from .service import Service, Tenant, TenantWithContainer, CoarseTenant, ServicePrivilege, TenantRoot, TenantRootPrivilege, TenantRootRole, TenantPrivilege, TenantRole, Subscriber, Provider
 from .service import ServiceAttribute, TenantAttribute, ServiceRole
 from .service import ServiceController, ServiceControllerResource
diff --git a/xos/core/models/xosmodel.py b/xos/core/models/xosmodel.py
index c632f08..7d686bd 100644
--- a/xos/core/models/xosmodel.py
+++ b/xos/core/models/xosmodel.py
@@ -5,8 +5,12 @@
 
 # XOS: Serves as the root of the build system
 
+
+
 class XOS(PlCoreBase):
     name = StrippedCharField(max_length=200, unique=True, help_text="Name of XOS", default="XOS")
+    ui_port = models.IntegerField(help_text="Port for XOS UI", default=80)
+    db_container_name = StrippedCharField(max_length=200, help_text="name of XOS db container", default="xos_db")
 
     def __unicode__(self):  return u'%s' % (self.name)
 
@@ -26,4 +30,12 @@
             service_controller.save()
         self.save()
 
+class XOSVolume(PlCoreBase):
+    xos = models.ForeignKey(XOS, related_name='volumes', help_text="The XOS object for this Volume")
+    container_path=StrippedCharField(max_length=1024, unique=True, help_text="Path of Volume in Container")
+    host_path=StrippedCharField(max_length=1024, help_text="Path of Volume in Host")
+    read_only=models.BooleanField(default=False, help_text="True if mount read-only")
+
+    def __unicode__(self): return u'%s' % (self.container_path)
+
 
diff --git a/xos/tosca/custom_types/xos.m4 b/xos/tosca/custom_types/xos.m4
index c297529..f7f9ca1 100644
--- a/xos/tosca/custom_types/xos.m4
+++ b/xos/tosca/custom_types/xos.m4
@@ -10,6 +10,20 @@
         derived_from: tosca.nodes.Root
         description: The root of XOS
 
+    tosca.nodes.XOSVolume:
+        derived_from: tosca.nodes.Root
+        description: A volume that should be attached to the XOS docker container
+        properties:
+            xos_base_props
+            host_path:
+                type: string
+                required: false
+                description: path of resource on host
+            read_only:
+                type: boolean
+                required: false
+                description: True if mount read only
+
     tosca.nodes.Service:
         derived_from: tosca.nodes.Root
         description: >
@@ -1030,6 +1044,9 @@
     tosca.relationships.UsedByController:
         derived_from: tosca.relationships.Root
 
+    tosca.relationships.UsedByXOS:
+        derived_from: tosca.relationships.Root
+
     tosca.capabilities.xos.Service:
         derived_from: tosca.capabilities.Root
         description: An XOS Service
diff --git a/xos/tosca/custom_types/xos.yaml b/xos/tosca/custom_types/xos.yaml
index d17b679..c912e1a 100644
--- a/xos/tosca/custom_types/xos.yaml
+++ b/xos/tosca/custom_types/xos.yaml
@@ -25,6 +25,35 @@
         derived_from: tosca.nodes.Root
         description: The root of XOS
 
+    tosca.nodes.XOSVolume:
+        derived_from: tosca.nodes.Root
+        description: A volume that should be attached to the XOS docker container
+        properties:
+            no-delete:
+                type: boolean
+                default: false
+                description: Do not allow Tosca to delete this object
+            no-create:
+                type: boolean
+                default: false
+                description: Do not allow Tosca to create this object
+            no-update:
+                type: boolean
+                default: false
+                description: Do not allow Tosca to update this object
+            replaces:
+                type: string
+                required: false
+                descrption: Replaces/renames this object
+            host_path:
+                type: string
+                required: false
+                description: path of resource on host
+            read_only:
+                type: boolean
+                required: false
+                description: True if mount read only
+
     tosca.nodes.Service:
         derived_from: tosca.nodes.Root
         description: >
@@ -1809,6 +1838,9 @@
     tosca.relationships.UsedByController:
         derived_from: tosca.relationships.Root
 
+    tosca.relationships.UsedByXOS:
+        derived_from: tosca.relationships.Root
+
     tosca.capabilities.xos.Service:
         derived_from: tosca.capabilities.Root
         description: An XOS Service
diff --git a/xos/tosca/resources/xosmodel.py b/xos/tosca/resources/xosmodel.py
index 29ee1a1..2132f07 100644
--- a/xos/tosca/resources/xosmodel.py
+++ b/xos/tosca/resources/xosmodel.py
@@ -5,7 +5,7 @@
 sys.path.append("/opt/tosca")
 from translator.toscalib.tosca_template import ToscaTemplate
 
-from core.models import XOS
+from core.models import XOS, XOSVolume
 
 from xosresource import XOSResource
 
@@ -13,5 +13,17 @@
     provides = "tosca.nodes.XOS"
     xos_model = XOS
 
+class XOSVolume(XOSResource):
+    provides = "tosca.nodes.XOSVolume"
+    xos_model = XOSVolume
+    copyin_props = ["host_path"]
+    name_field = "container_path"
 
+    def get_xos_args(self, throw_exception=True):
+        args = super(XOSVolume, self).get_xos_args()
 
+        xos_name = self.get_requirement("tosca.relationships.UsedByXOS", throw_exception=throw_exception)
+        if xos_name:
+            args["xos"] = self.get_xos_object(XOS, throw_exception=throw_exception, name=xos_name)
+
+        return args
diff --git a/xos/tosca/resources/xosresource.py b/xos/tosca/resources/xosresource.py
index 012f814..f65a231 100644
--- a/xos/tosca/resources/xosresource.py
+++ b/xos/tosca/resources/xosresource.py
@@ -189,6 +189,17 @@
 
         raise Exception("artifact %s not found" % name)
 
+    def intrinsic_path_join(self, obj=None, name=None, varname=None, method=None):
+        if obj!="SELF":
+            raise Exception("only SELF is supported for get_artifact first arg")
+        if method!="ENV_VAR":
+            raise Exception("only ENV_VAR is supported for get_artifact fourth arg")
+
+        if not (name in os.environ):
+            raise Exception("environment variable %s not found" % name)
+
+        return os.path.join(os.environ[name], varname)
+
     def try_intrinsic_function(self, v):
         try:
             jsv = v.replace("'", '"')
@@ -205,6 +216,8 @@
             return self.intrinsic_get_artifact(*jsv["get_artifact"])
         elif "get_script_env" in jsv:
             return self.intrinsic_get_script_env(*jsv["get_script_env"])
+        elif "path_join" in jsv:
+            return self.intrinsic_path_join(*jsv["path_join"])
 
         return v