Creating the new rest container
Defining XOS Components in the form of containers
Change-Id: Id0c982e8ad5dc51a37462eb5ef55fa50a4be23fb
diff --git a/xos/core/models/__init__.py b/xos/core/models/__init__.py
index 4138b22..de3a941 100644
--- a/xos/core/models/__init__.py
+++ b/xos/core/models/__init__.py
@@ -5,6 +5,7 @@
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, LoadableModule, LoadableModuleResource, Library
+from .service import XOSComponent, XOSComponentLink, XOSComponentVolume
from .tag import Tag
from .role import Role
from .site import Site, Deployment, DeploymentRole, DeploymentPrivilege, Controller, ControllerRole, ControllerSite, SiteDeployment,Diag
diff --git a/xos/core/models/service.py b/xos/core/models/service.py
index 894033a..8f874e3 100644
--- a/xos/core/models/service.py
+++ b/xos/core/models/service.py
@@ -193,6 +193,36 @@
# for now, it's exactly like a LoadableModule
pass
+
+class XOSComponent(LoadableModule):
+ # this will define loadable XOS component in the form of containers
+ image = StrippedCharField(max_length=200, help_text="docker image name")
+ command = StrippedCharField(max_length=1024, help_text="docker run command", null=True, blank=True)
+ ports = StrippedCharField(max_length=200, help_text="port binding", null=True, blank=True)
+
+
+class XOSComponentLink(PlCoreBase):
+
+ LINK_KIND = (
+ ('internal', 'Internal'),
+ ('external', 'External')
+ )
+
+ component = models.ForeignKey(XOSComponent, related_name='links', help_text="The Component object for this Link")
+ container = StrippedCharField(max_length=200, help_text="container to link")
+ alias = StrippedCharField(max_length=200, help_text="alias for the link")
+ kind = models.CharField(max_length=20, choices=LINK_KIND, default='internal')
+
+
+# NOTE can this be the same of XOSVolume??
+class XOSComponentVolume(PlCoreBase):
+ component = models.ForeignKey(XOSComponent, related_name='volumes', help_text="The Component object for this Volume")
+ name = StrippedCharField(max_length=30, help_text="Volume Name")
+ 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")
+
+
class ServiceController(LoadableModule):
synchronizer_run = StrippedCharField(max_length=1024, help_text="synchronizer run command", null=True, blank=True)
synchronizer_config = StrippedCharField(max_length=1024, help_text="synchronizer config file", null=True, blank=True)
diff --git a/xos/synchronizers/onboarding/steps/sync_component.py b/xos/synchronizers/onboarding/steps/sync_component.py
new file mode 100644
index 0000000..128c98f
--- /dev/null
+++ b/xos/synchronizers/onboarding/steps/sync_component.py
@@ -0,0 +1,47 @@
+import os
+import sys
+import base64
+from django.db.models import F, Q
+from xos.config import Config
+from synchronizers.base.syncstep import SyncStep, DeferredException
+from core.models import XOS, XOSComponent
+from xos.logger import Logger, logging
+from synchronizers.base.ansible import run_template
+
+# xosbuilder will be in steps/..
+parentdir = os.path.join(os.path.dirname(__file__),"..")
+sys.path.insert(0,parentdir)
+
+from xosbuilder import XOSBuilder
+
+logger = Logger(level=logging.INFO)
+
+class SyncXOSComponent(SyncStep, XOSBuilder):
+ provides=[XOSComponent]
+ observes=XOSComponent
+ requested_interval=0
+
+ def __init__(self, **args):
+ SyncStep.__init__(self, **args)
+ XOSBuilder.__init__(self)
+
+ def sync_record(self, sc):
+ logger.info("Sync'ing XOSComponent %s" % sc)
+
+ if sc.xos and (not sc.xos.enable_build):
+ raise DeferredException("XOS build is currently disabled")
+
+ unready = self.check_controller_unready(sc)
+ if unready:
+ raise Exception("Controller %s has unready resources: %s" % (str(sc), ",".join([str(x) for x in unready])))
+
+ # There's nothing to actually do, since there's no synchronizer
+ # container for libraries.
+
+ def delete_record(self, m):
+ pass
+
+ def fetch_pending(self, deleted=False):
+ pend = super(SyncXOSComponent, self).fetch_pending(deleted)
+ return pend
+
diff --git a/xos/synchronizers/onboarding/xosbuilder.py b/xos/synchronizers/onboarding/xosbuilder.py
index c23f996..c791f1f 100644
--- a/xos/synchronizers/onboarding/xosbuilder.py
+++ b/xos/synchronizers/onboarding/xosbuilder.py
@@ -8,24 +8,26 @@
import xmlrpclib
from xos.config import Config
-from core.models import Service, ServiceController, ServiceControllerResource, LoadableModule, LoadableModuleResource, XOS
+from core.models import Service, ServiceController, ServiceControllerResource, LoadableModule, LoadableModuleResource, XOS, XOSComponent
from xos.logger import Logger, logging
from django.utils import timezone
logger = Logger(level=logging.INFO)
+
def add_unique(list, item):
- if not item in list:
- list.append(item)
+ if not item in list:
+ list.append(item)
+
class XOSBuilder(object):
- UI_KINDS=["models", "admin", "admin_template", "django_library", "rest_service", "rest_tenant", "tosca_custom_types", "tosca_resource","public_key","vendor_js"]
- SYNC_CONTROLLER_KINDS=["synchronizer", "private_key", "public_key"]
- SYNC_ALLCONTROLLER_KINDS=["models", "django_library"]
+ UI_KINDS = ["models", "admin", "admin_template", "django_library", "rest_service", "rest_tenant", "tosca_custom_types", "tosca_resource","public_key","vendor_js"]
+ SYNC_CONTROLLER_KINDS = ["synchronizer", "private_key", "public_key"]
+ SYNC_ALLCONTROLLER_KINDS = ["models", "django_library"]
def __init__(self):
- self.source_sync_image = "xosproject/xos" # "xosproject/xos-synchronizer-openstack"
+ self.source_sync_image = "xosproject/xos" # "xosproject/xos-synchronizer-openstack"
self.build_dir = "/opt/xos/BUILD/"
self.build_tainted = False
@@ -74,13 +76,13 @@
manifest_lines = [x for x in manifest_lines if x]
for line in manifest_lines:
url_parts = urlparse.urlsplit(scr.full_url)
- new_path = os.path.join(os.path.join(*os.path.split(url_parts.path)[:-1]),line)
- url = urlparse.urlunsplit( (url_parts.scheme, url_parts.netloc, new_path, url_parts.query, url_parts.fragment) )
+ new_path = os.path.join(os.path.join(*os.path.split(url_parts.path)[:-1]), line)
+ url = urlparse.urlunsplit((url_parts.scheme, url_parts.netloc, new_path, url_parts.query, url_parts.fragment))
build_fn = os.path.join(self.get_dest_dir(scr), line)
download_fn = os.path.join(self.build_dir, build_fn)
- manifest.append( (url, download_fn, build_fn) )
+ manifest.append((url, download_fn, build_fn))
return manifest
def download_file(self, url, dest_fn):
@@ -88,10 +90,10 @@
if not os.path.exists(os.path.dirname(dest_fn)):
os.makedirs(os.path.dirname(dest_fn))
obj = urllib2.urlopen(url)
- file(dest_fn,"w").write(obj.read())
+ file(dest_fn, "w").write(obj.read())
# make python files executable
- if dest_fn.endswith(".py"): # and contents.startswith("#!"):
+ if dest_fn.endswith(".py"): # and contents.startswith("#!"):
os.chmod(dest_fn, 0755)
def download_resource(self, scr):
@@ -145,8 +147,8 @@
manifest = self.read_manifest(scr, manifest_fn)
lines = []
for (url, download_fn, build_fn) in manifest:
- lines.append("mkdir -p /%s" % os.path.dirname(build_fn))
- lines.append("cp /build/%s /%s" % (build_fn, build_fn))
+ lines.append("mkdir -p /%s" % os.path.dirname(build_fn))
+ lines.append("cp /build/%s /%s" % (build_fn, build_fn))
return lines
else:
build_fn = self.get_build_fn(scr)
@@ -155,8 +157,8 @@
def get_controller_script_lines(self, controller, kinds):
need_service_init_py = False
- script=[]
- inits=[]
+ script = []
+ inits = []
for scr in list(controller.loadable_module_resources.all()):
if not (scr.kind in kinds):
continue
@@ -191,12 +193,12 @@
add_unique(inits, dir)
for init in inits:
- script.append("echo > %s" % os.path.join("/",init,"__init__.py"))
+ script.append("echo > %s" % os.path.join("/", init, "__init__.py"))
return script
def check_controller_unready(self, controller):
- unready_resources=[]
+ unready_resources = []
for scr in controller.loadable_module_resources.all():
if (not scr.backend_status) or (not scr.backend_status.startswith("1")):
unready_resources.append(scr)
@@ -206,19 +208,19 @@
# stuff that has to do with building
def create_xos_app_data(self, name, script, app_list, migration_list):
- if not os.path.exists(os.path.join(self.build_dir,"opt/xos/xos")):
- os.makedirs(os.path.join(self.build_dir,"opt/xos/xos"))
+ if not os.path.exists(os.path.join(self.build_dir, "opt/xos/xos")):
+ os.makedirs(os.path.join(self.build_dir, "opt/xos/xos"))
if app_list:
script.append("mkdir -p /opt/xos/xos")
script.append("cp /build/opt/xos/xos/%s_xosbuilder_app_list /opt/xos/xos/xosbuilder_app_list" % name)
- #dockerfile.append("COPY opt/xos/xos/%s_xosbuilder_app_list /opt/xos/xos/xosbuilder_app_list" % name)
+ # dockerfile.append("COPY opt/xos/xos/%s_xosbuilder_app_list /opt/xos/xos/xosbuilder_app_list" % name)
file(os.path.join(self.build_dir, "opt/xos/xos/%s_xosbuilder_app_list") % name, "w").write("\n".join(app_list)+"\n")
if migration_list:
script.append("mkdir -p /opt/xos/xos")
script.append("cp /build/opt/xos/xos/%s_xosbuilder_migration_list /opt/xos/xos/xosbuilder_migration_list" % name)
- #dockerfile.append("COPY opt/xos/xos/%s_xosbuilder_migration_list /opt/xos/xos/xosbuilder_migration_list" % name)
+ # dockerfile.append("COPY opt/xos/xos/%s_xosbuilder_migration_list /opt/xos/xos/xosbuilder_migration_list" % name)
file(os.path.join(self.build_dir, "opt/xos/xos/%s_xosbuilder_migration_list") % name, "w").write("\n".join(migration_list)+"\n")
def create_ui_dockerfile(self):
@@ -233,10 +235,10 @@
script = []
for controller in LoadableModule.objects.all():
if self.check_controller_unready(controller):
- logger.warning("Loadable Module %s has unready resources" % str(controller))
- continue
+ logger.warning("Loadable Module %s has unready resources" % str(controller))
+ continue
- #dockerfile = dockerfile + self.get_controller_docker_lines(controller, self.UI_KINDS)
+ # dockerfile = dockerfile + self.get_controller_docker_lines(controller, self.UI_KINDS)
script = script + self.get_controller_script_lines(controller, self.UI_KINDS)
if controller.loadable_module_resources.filter(kind="models").exists():
app_list.append("services." + controller.name)
@@ -304,42 +306,43 @@
"docker_image_name": "xosproject/xos-synchronizer-%s" % controller.name}
def create_docker_compose(self):
- xos = XOS.objects.all()[0]
+ xos = XOS.objects.all()[0]
- volume_list = []
- for volume in xos.volumes.all():
- volume_list.append({"host_path": volume.host_path,
- "container_path": volume.container_path,
- "read_only": volume.read_only})
+ volume_list = []
+ for volume in xos.volumes.all():
+ volume_list.append({"host_path": volume.host_path,
+ "container_path": volume.container_path,
+ "read_only": volume.read_only})
- if xos.extra_hosts:
- extra_hosts = [x.strip() for x in xos.extra_hosts.split(",")]
- else:
- extra_hosts = []
+ if xos.extra_hosts:
+ extra_hosts = [x.strip() for x in xos.extra_hosts.split(",")]
+ else:
+ extra_hosts = []
- containers = {}
+ containers = {}
# containers["xos_db"] = \
# {"image": "xosproject/xos-postgres",
# "expose": [5432]}
- external_links=[]
- if xos.db_container_name:
- external_links.append("%s:%s" % (xos.db_container_name, "xos_db"))
- if xos.redis_container_name:
- external_links.append("%s:%s" % (xos.redis_container_name, "redis"))
+ external_links = []
+ if xos.db_container_name:
+ external_links.append("%s:%s" % (xos.db_container_name, "xos_db"))
+ if xos.redis_container_name:
+ external_links.append("%s:%s" % (xos.redis_container_name, "redis"))
- containers["xos_ui"] = \
- {"image": "xosproject/xos-ui",
- "command": "python /opt/xos/manage.py runserver 0.0.0.0:%d --insecure --makemigrations" % xos.ui_port,
- "ports": {"%d"%xos.ui_port : "%d"%xos.ui_port},
- #"links": ["xos_db"],
- "external_links": external_links,
- "extra_hosts": extra_hosts,
- "volumes": volume_list}
+ containers["xos_ui"] = {
+ "image": "xosproject/xos-ui",
+ "command": "python /opt/xos/manage.py runserver 0.0.0.0:%d --insecure --makemigrations" % xos.ui_port,
+ "ports": {"%d" % xos.ui_port: "%d" % xos.ui_port},
+ # "links": ["xos_db"],
+ # "external_links": ["%s:%s" % (xos.db_container_name, "xos_db")],
+ "external_links": external_links,
+ "extra_hosts": extra_hosts,
+ "volumes": volume_list}
- if xos.no_start:
- containers["xos_ui"]["command"] = "sleep 864000"
+ if xos.no_start:
+ containers["xos_ui"]["command"] = "sleep 864000"
# containers["xos_bootstrap_ui"] = {"image": "xosproject/xos",
# "command": "python /opt/xos/manage.py runserver 0.0.0.0:%d --insecure --makemigrations" % xos.bootstrap_ui_port,
@@ -348,38 +351,70 @@
# "links": ["xos_db"],
# "volumes": volume_list}
- if not xos.frontend_only:
- for c in ServiceController.objects.all():
- if self.check_controller_unready(c):
- logger.warning("Controller %s has unready resources" % str(c))
- continue
+ # creating Component containers
+ for c in XOSComponent.objects.all():
- if c.loadable_module_resources.filter(kind="synchronizer").exists():
- if c.synchronizer_run and c.synchronizer_config:
- command = 'bash -c "sleep 120; cd /opt/xos/synchronizers/%s; python ./%s -C %s"' % (c.name, c.synchronizer_run, c.synchronizer_config)
- else:
- command = 'bash -c "sleep 120; cd /opt/xos/synchronizers/%s; bash ./run.sh"' % c.name
+ # create internal and external links list
+ links = []
+ external_links = []
+ for l in c.links.all():
+ if l.kind == 'internal':
+ links.append("%s:%s" % (l.container, l.alias))
+ elif l.kind == 'external':
+ external_links.append("%s:%s" % (l.container, l.alias))
- containers["xos_synchronizer_%s" % c.name] = \
- {"image": "xosproject/xos-synchronizer-%s" % c.name,
- "command": command,
- "external_links": external_links,
- "extra_hosts": extra_hosts,
- "volumes": volume_list}
+ # creating volumes list
+ volume_list = []
+ for volume in c.volumes.all():
+ volume_list.append({"host_path": volume.host_path,
+ "container_path": volume.container_path,
+ "read_only": volume.read_only})
- if c.no_start:
- containers["xos_synchronizer_%s" % c.name]["command"] = "sleep 864000"
+ port = c.ports.split(":")
+ containers[c.name] = {
+ "image": c.image,
+ "command": c.command,
+ "ports": {
+ port[0]: port[1]
+ },
+ "links": links,
+ "external_links": external_links,
+ "volumes": volume_list
+ }
- vars = { "containers": containers }
+ if not xos.frontend_only:
+ for c in ServiceController.objects.all():
+ if self.check_controller_unready(c):
+ logger.warning("Controller %s has unready resources" % str(c))
+ continue
- template_loader = jinja2.FileSystemLoader( "/opt/xos/synchronizers/onboarding/templates/" )
- template_env = jinja2.Environment(loader=template_loader)
- template = template_env.get_template("docker-compose.yml.j2")
- buffer = template.render(vars)
+ if c.loadable_module_resources.filter(kind="synchronizer").exists():
+ if c.synchronizer_run and c.synchronizer_config:
+ command = 'bash -c "sleep 120; cd /opt/xos/synchronizers/%s; python ./%s -C %s"' % (c.name, c.synchronizer_run, c.synchronizer_config)
+ else:
+ command = 'bash -c "sleep 120; cd /opt/xos/synchronizers/%s; bash ./run.sh"' % c.name
- if not os.path.exists("/opt/xos/synchronizers/onboarding/docker-compose"):
- os.makedirs("/opt/xos/synchronizers/onboarding/docker-compose")
- file("/opt/xos/synchronizers/onboarding/docker-compose/docker-compose.yml", "w").write(buffer)
+ containers["xos_synchronizer_%s" % c.name] = {
+ "image": "xosproject/xos-synchronizer-%s" % c.name,
+ "command": command,
+ "external_links": ["%s:%s" % (xos.db_container_name, "xos_db")],
+ "extra_hosts": extra_hosts,
+ "volumes": volume_list
+ }
+
+ if c.no_start:
+ containers["xos_synchronizer_%s" % c.name]["command"] = "sleep 864000"
+
+ vars = {"containers": containers}
+
+ template_loader = jinja2.FileSystemLoader("/opt/xos/synchronizers/onboarding/templates/")
+ template_env = jinja2.Environment(loader=template_loader)
+ template = template_env.get_template("docker-compose.yml.j2")
+ buffer = template.render(vars)
+
+ if not os.path.exists("/opt/xos/synchronizers/onboarding/docker-compose"):
+ os.makedirs("/opt/xos/synchronizers/onboarding/docker-compose")
+ file("/opt/xos/synchronizers/onboarding/docker-compose/docker-compose.yml", "w").write(buffer)
# def build_xos(self):
# dockerfiles=[]
@@ -387,6 +422,3 @@
#
# for controller in ServiceController.objects.all():
# dockerfiles.append(self.create_synchronizer_dockerfile(controller))
-
-
-
diff --git a/xos/tosca/custom_types/xos.m4 b/xos/tosca/custom_types/xos.m4
index 4cbf675..b0d5b32 100644
--- a/xos/tosca/custom_types/xos.m4
+++ b/xos/tosca/custom_types/xos.m4
@@ -48,7 +48,6 @@
required: false
description: List of extra_hosts to pass to docker compose
-
tosca.nodes.XOSVolume:
derived_from: tosca.nodes.Root
description: A volume that should be attached to the XOS docker container
@@ -239,6 +238,73 @@
required: false
description: third-party javascript files
+ tosca.nodes.Component:
+ derived_from: tosca.nodes.Root
+ description: >
+ An XOS Component in the form of a docker container.
+ properties:
+ xos_base_props
+ name:
+ type: string
+ required: true
+ description: the container name
+ image:
+ type: string
+ required: true
+ description: the base image for the container
+ command:
+ type: string
+ required: false
+ description: the command to execute in the container
+ ports:
+ type: string
+ required: false
+ description: ports that need to be exposed
+
+ tosca.nodes.ComponentLink:
+ derived_from: tosca.nodes.Root
+ description: >
+ Links between XOS components.
+ properties:
+ xos_base_props
+ container:
+ type: string
+ required: true
+ description: the container that needs to be linked
+ alias:
+ type: string
+ required: true
+ description: alias for the link
+ kind:
+ type: string
+ required: true
+ description: internal or external link
+ constraints:
+ - valid_values: [ 'internal', 'external' ]
+
+ tosca.nodes.ComponentVolume:
+ derived_from: tosca.nodes.Root
+ description: >
+ Volumes of the XOS components.
+ 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.relationships.LinkOfComponent:
+ derived_from: tosca.relationships.Root
+ valid_target_types: [ tosca.capabilities.xos.ComponentLink ]
+
+ tosca.relationships.VolumeOfComponent:
+ derived_from: tosca.relationships.Root
+ valid_target_types: [ tosca.capabilities.xos.ComponentVolume ]
+
tosca.nodes.Tenant:
derived_from: tosca.nodes.Root
description: >
diff --git a/xos/tosca/custom_types/xos.yaml b/xos/tosca/custom_types/xos.yaml
index fc9eb42..d3baf30 100644
--- a/xos/tosca/custom_types/xos.yaml
+++ b/xos/tosca/custom_types/xos.yaml
@@ -78,7 +78,6 @@
required: false
description: List of extra_hosts to pass to docker compose
-
tosca.nodes.XOSVolume:
derived_from: tosca.nodes.Root
description: A volume that should be attached to the XOS docker container
@@ -377,6 +376,118 @@
required: false
description: third-party javascript files
+ tosca.nodes.Component:
+ derived_from: tosca.nodes.Root
+ description: >
+ An XOS Component in the form of a 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
+ name:
+ type: string
+ required: true
+ description: the container name
+ image:
+ type: string
+ required: true
+ description: the base image for the container
+ command:
+ type: string
+ required: false
+ description: the command to execute in the container
+ ports:
+ type: string
+ required: false
+ description: ports that need to be exposed
+
+ tosca.nodes.ComponentLink:
+ derived_from: tosca.nodes.Root
+ description: >
+ Links between XOS components.
+ 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
+ container:
+ type: string
+ required: true
+ description: the container that needs to be linked
+ alias:
+ type: string
+ required: true
+ description: alias for the link
+ kind:
+ type: string
+ required: true
+ description: internal or external link
+ constraints:
+ - valid_values: [ 'internal', 'external' ]
+
+ tosca.nodes.ComponentVolume:
+ derived_from: tosca.nodes.Root
+ description: >
+ Volumes of the XOS components.
+ 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.relationships.LinkOfComponent:
+ derived_from: tosca.relationships.Root
+ valid_target_types: [ tosca.capabilities.xos.ComponentLink ]
+
+ tosca.relationships.VolumeOfComponent:
+ derived_from: tosca.relationships.Root
+ valid_target_types: [ tosca.capabilities.xos.ComponentVolume ]
+
tosca.nodes.Tenant:
derived_from: tosca.nodes.Root
description: >
diff --git a/xos/tosca/resources/xoscomponent.py b/xos/tosca/resources/xoscomponent.py
new file mode 100644
index 0000000..f74cfde
--- /dev/null
+++ b/xos/tosca/resources/xoscomponent.py
@@ -0,0 +1,40 @@
+from xosresource import XOSResource
+from core.models import XOSComponent, XOSComponentLink, XOSComponentVolume
+
+
+class XOSXOSComponent(XOSResource):
+ provides = "tosca.nodes.Component"
+ xos_model = XOSComponent
+ copyin_props = ["name", "image", "command", "ports"]
+
+
+class XOSXOSComponentLink(XOSResource):
+ provides = "tosca.nodes.ComponentLink"
+ xos_model = XOSComponentLink
+ copyin_props = ["container", "alias", "kind"]
+ name_field = "container"
+
+ def get_xos_args(self, throw_exception=True):
+ args = super(XOSXOSComponentLink, self).get_xos_args()
+
+ component_name = self.get_requirement("tosca.relationships.LinkOfComponent", throw_exception=throw_exception)
+ if component_name:
+ args["component"] = self.get_xos_object(XOSComponent, throw_exception=throw_exception, name=component_name)
+
+ return args
+
+
+class XOSXOSComponentVolume(XOSResource):
+ provides = "tosca.nodes.ComponentVolume"
+ xos_model = XOSComponentVolume
+ copyin_props = ["host_path", "read_only"]
+ name_field = "container_path"
+
+ def get_xos_args(self, throw_exception=True):
+ args = super(XOSXOSComponentVolume, self).get_xos_args()
+
+ component_name = self.get_requirement("tosca.relationships.VolumeOfComponent", throw_exception=throw_exception)
+ if component_name:
+ args["component"] = self.get_xos_object(XOSComponent, throw_exception=throw_exception, name=component_name)
+
+ return args