Merge branch 'master' of https://github.com/open-cloud/xos
diff --git a/xos/configurations/cord/Makefile b/xos/configurations/cord/Makefile
index 4c2e423..86b4ca1 100644
--- a/xos/configurations/cord/Makefile
+++ b/xos/configurations/cord/Makefile
@@ -2,7 +2,7 @@
RUNNING_CONTAINER:=$(shell sudo docker ps|grep "xos"|awk '{print $$NF}')
LAST_CONTAINER=$(shell sudo docker ps -l -q)
-test: common_cloudlab ceilometer_dashboard
+cord: common_cloudlab ceilometer_dashboard
echo "# Autogenerated -- do not edit" > Dockerfile
cat ../common/Dockerfile.common Dockerfile.cord >> Dockerfile
cd ../../..; sudo docker build -t xos -f xos/configurations/cord/Dockerfile .
diff --git a/xos/configurations/cord/cord.yaml b/xos/configurations/cord/cord.yaml
index e9a6291..67d8bb6 100644
--- a/xos/configurations/cord/cord.yaml
+++ b/xos/configurations/cord/cord.yaml
@@ -58,7 +58,7 @@
# - (Synchronizer should copy the files to ONOS container immediately)
# - Log into service_ONOS_vBNG VM and restart ONOS Docker container
# (Should roll this step into a Synchronizer)
-#
+#f
vBNG_ONOS_app:
type: tosca.nodes.ONOSvBNGApp
requirements:
@@ -116,6 +116,7 @@
artifacts:
pubkey: /opt/xos/observers/onos/onos_key.pub
+
vOLT_ONOS_app:
type: tosca.nodes.ONOSvOLTApp
requirements:
@@ -127,6 +128,20 @@
relationship: tosca.relationships.UsedByService
properties:
dependencies: org.onosproject.olt
+ config_network-cfg.json: >
+ {
+ "devices" : {
+ "of:0000000000000001" : {
+ "accessDevice" : {
+ "uplink" : "2",
+ "vlan" : "400"
+ },
+ "basic" : {
+ "driver" : "default"
+ }
+ }
+ }
+ }
# Network templates
Private:
diff --git a/xos/configurations/cord/dataplane/generate.sh b/xos/configurations/cord/dataplane/generate.sh
index 360ed67..49a12ef 100755
--- a/xos/configurations/cord/dataplane/generate.sh
+++ b/xos/configurations/cord/dataplane/generate.sh
@@ -14,5 +14,8 @@
switch_vbng ansible_ssh_host=$( get_ip mysite_vbng flat-lan-1-net) wan_ip=$( get_ip mysite_vbng wan_network) public_ip=$( get_ip mysite_vbng tun0-net )
onos_volt ansible_ssh_host=$( get_ip mysite_onos_volt flat-lan-1-net)
-switch_volt ansible_ssh_host=$( get_ip mysite_volt flat-lan-1-net) subscriber_ip=$( get_ip mysite_volt subscriber_network) lan_ip=$( get_ip mysite_volt lan_network) vcpe_lan_ip=$( get_ip mysite_vcpe lan_network)
+switch_volt ansible_ssh_host=$( get_ip mysite_volt flat-lan-1-net) subscriber_ip=$( get_ip mysite_volt subscriber_network) lan_ip=$( get_ip mysite_volt lan_network)
+
+client ansible_ssh_host=$( get_ip mysite_clients flat-lan-1-net) subscriber_ip=$( get_ip mysite_clients subscriber_network)
+vcpe ansible_ssh_host=$( get_ip mysite_vcpe flat-lan-1-net) lan_ip=$( get_ip mysite_vcpe lan_network)
EOF
diff --git a/xos/cord/admin.py b/xos/cord/admin.py
index 6137212..9e7946e 100644
--- a/xos/cord/admin.py
+++ b/xos/cord/admin.py
@@ -1,6 +1,7 @@
from django.contrib import admin
from cord.models import *
+from core.models import Container
from django import forms
from django.utils.safestring import mark_safe
from django.contrib.auth.admin import UserAdmin
@@ -159,6 +160,8 @@
bbs_account = forms.CharField(required=False)
creator = forms.ModelChoiceField(queryset=User.objects.all())
instance = forms.ModelChoiceField(queryset=Instance.objects.all(),required=False)
+ container = forms.ModelChoiceField(queryset=Container.objects.all(),required=False)
+ use_cobm = forms.BooleanField(required=False)
last_ansible_hash = forms.CharField(required=False)
def __init__(self,*args,**kwargs):
@@ -170,6 +173,8 @@
self.fields['bbs_account'].initial = self.instance.bbs_account
self.fields['creator'].initial = self.instance.creator
self.fields['instance'].initial = self.instance.instance
+ self.fields['container'].initial = self.instance.container
+ self.fields['use_cobm'].initial = self.instance.use_cobm
self.fields['last_ansible_hash'].initial = self.instance.last_ansible_hash
if (not self.instance) or (not self.instance.pk):
# default fields for an 'add' form
@@ -177,11 +182,14 @@
self.fields['creator'].initial = get_request().user
if VCPEService.get_service_objects().exists():
self.fields["provider_service"].initial = VCPEService.get_service_objects().all()[0]
+ self.fields['use_cobm'].initial = False
def save(self, commit=True):
self.instance.creator = self.cleaned_data.get("creator")
self.instance.instance = self.cleaned_data.get("instance")
self.instance.last_ansible_hash = self.cleaned_data.get("last_ansible_hash")
+ self.instance.container = self.cleaned_data.get("container")
+ self.instance.use_cobm = self.cleaned_data.get("use_cobm")
return super(VCPETenantForm, self).save(commit=commit)
class Meta:
@@ -191,7 +199,7 @@
list_display = ('backend_status_icon', 'id', 'subscriber_tenant' )
list_display_links = ('backend_status_icon', 'id')
fieldsets = [ (None, {'fields': ['backend_status_text', 'kind', 'provider_service', 'subscriber_tenant', 'service_specific_id', # 'service_specific_attribute',
- 'bbs_account', 'creator', 'instance', 'last_ansible_hash'],
+ 'bbs_account', 'creator', 'use_cobm', 'instance', 'container', 'last_ansible_hash'],
'classes':['suit-tab suit-tab-general']})]
readonly_fields = ('backend_status_text', 'service_specific_attribute', 'bbs_account')
form = VCPETenantForm
diff --git a/xos/cord/models.py b/xos/cord/models.py
index 67ffdc7..4227f52 100644
--- a/xos/cord/models.py
+++ b/xos/cord/models.py
@@ -333,6 +333,7 @@
vcpe = VCPETenant(provider_service = vcpeServices[0],
subscriber_tenant = self)
vcpe.caller = self.creator
+ # vcpe.use_cobm = True # XXX XXX XXX remove before checking XXX XXX XXX
vcpe.save()
def manage_subscriber(self):
@@ -470,6 +471,7 @@
"hpc_client_ip", "hpc_client_mac")
default_attributes = {"instance_id": None,
+ "container_id": None,
"users": [],
"bbs_account": None,
"last_ansible_hash": None}
@@ -534,11 +536,15 @@
@property
def addresses(self):
- if not self.instance:
+ if self.instance:
+ ports = self.instance.ports.all()
+ elif self.container:
+ ports = self.container.ports.all()
+ else:
return {}
addresses = {}
- for ns in self.instance.ports.all():
+ for ns in ports:
if "lan" in ns.network.name.lower():
addresses["lan"] = (ns.ip, ns.mac)
elif "wan" in ns.network.name.lower():
diff --git a/xos/core/admin.py b/xos/core/admin.py
index a0cabd1..317c6a5 100644
--- a/xos/core/admin.py
+++ b/xos/core/admin.py
@@ -1384,7 +1384,7 @@
class ContainerAdmin(XOSBaseAdmin):
fieldsets = [
- ('Container Details', {'fields': ['backend_status_text', 'slice', 'node', 'docker_image', 'no_sync'], 'classes': ['suit-tab suit-tab-general'], })
+ ('Container Details', {'fields': ['backend_status_text', 'slice', 'node', 'docker_image', 'volumes', 'no_sync'], 'classes': ['suit-tab suit-tab-general'], })
]
readonly_fields = ('backend_status_text', )
list_display = ['backend_status_icon', 'id']
diff --git a/xos/core/models/container.py b/xos/core/models/container.py
index 151b576..ae1d198 100644
--- a/xos/core/models/container.py
+++ b/xos/core/models/container.py
@@ -28,6 +28,7 @@
node = models.ForeignKey(Node, related_name='containers')
creator = models.ForeignKey(User, related_name='containers', blank=True, null=True)
docker_image = StrippedCharField(null=True, blank=True, max_length=200, help_text="name of docker container to instantiate")
+ volumes = models.TextField(null=True, blank=True, help_text="Comma-separated list of volumes")
def __unicode__(self):
return u'container-%s' % str(self.id)
diff --git a/xos/core/models/node.py b/xos/core/models/node.py
index ec67975..5496d6b 100644
--- a/xos/core/models/node.py
+++ b/xos/core/models/node.py
@@ -16,6 +16,10 @@
def __unicode__(self): return u'%s' % (self.name)
+ def __init__(self, *args, **kwargs):
+ super(Node, self).__init__(*args, **kwargs)
+ self.no_sync=True
+
def save(self, *args, **kwds):
if self.site is None and self.site_deployment is not None:
self.site = self.site_deployment.site
diff --git a/xos/core/models/service.py b/xos/core/models/service.py
index 950ce02..c263bba 100644
--- a/xos/core/models/service.py
+++ b/xos/core/models/service.py
@@ -353,6 +353,9 @@
super(TenantWithContainer, self).__init__(*args, **kwargs)
self.cached_instance=None
self.orig_instance_id = self.get_initial_attribute("instance_id")
+ self.cached_container=None
+ self.orig_container_id = self.get_initial_attribute("container_id")
+
@property
def instance(self):
@@ -379,6 +382,30 @@
self.set_attribute("instance_id", value)
@property
+ def container(self):
+ from core.models import Container
+ if getattr(self, "cached_container", None):
+ return self.cached_container
+ container_id=self.get_attribute("container_id")
+ if not container_id:
+ return None
+ containers=Container.objects.filter(id=container_id)
+ if not containers:
+ return None
+ container=containers[0]
+ container.caller = self.creator
+ self.cached_container = container
+ return container
+
+ @container.setter
+ def container(self, value):
+ if value:
+ value = value.id
+ if (value != self.get_attribute("container_id", None)):
+ self.cached_container=None
+ self.set_attribute("container_id", value)
+
+ @property
def creator(self):
from core.models import User
if getattr(self, "cached_creator", None):
@@ -413,7 +440,23 @@
raise XOSProgrammingError("No VPCE image (looked for %s)" % str(self.LOOK_FOR_IMAGES))
- def pick_node(self):
+ @property
+ def use_cobm(self):
+ return self.get_attribute("use_cobm", False)
+
+ @use_cobm.setter
+ def use_cobm(self, v):
+ self.set_attribute("use_cobm", v)
+
+ @creator.setter
+ def creator(self, value):
+ if value:
+ value = value.id
+ if (value != self.get_attribute("creator_id", None)):
+ self.cached_creator=None
+ self.set_attribute("creator_id", value)
+
+ def pick_node_for_instance(self):
from core.models import Node
nodes = list(Node.objects.all())
# TODO: logic to filter nodes by which nodes are up, and which
@@ -421,7 +464,15 @@
nodes = sorted(nodes, key=lambda node: node.instances.all().count())
return nodes[0]
- def manage_container(self):
+ def pick_node_for_container_on_metal(self):
+ from core.models import Node
+ nodes = list(Node.objects.all())
+ # TODO: logic to filter nodes by which nodes are up, and which
+ # nodes the slice can instantiate on.
+ nodes = sorted(nodes, key=lambda node: node.containers.all().count())
+ return nodes[0]
+
+ def manage_container_in_instance(self):
from core.models import Instance, Flavor
if self.deleted:
@@ -439,7 +490,7 @@
if not flavors:
raise XOSConfigurationError("No m1.small flavor")
- node =self.pick_node()
+ node =self.pick_node_for_instance()
instance = Instance(slice = self.provider_service.slices.all()[0],
node = node,
image = self.image,
@@ -455,11 +506,83 @@
instance.delete()
raise
+ def manage_container_on_metal(self):
+ from core.models import Container, Instance, Flavor, Port
+
+ if self.deleted:
+ return
+
+ if (self.container is not None):
+ self.container.delete()
+ self.container = None
+
+ if self.container is None:
+ if not self.provider_service.slices.count():
+ raise XOSConfigurationError("The VCPE service has no slices")
+
+ slice = self.provider_service.slices.all()[0]
+ node = self.pick_node_for_container_on_metal()
+
+ # Our current docker network strategy requires that there be some
+ # instance on the server that connects to the networks, so that
+ # the containers can piggyback off of that configuration.
+ instances = Instance.objects.filter(slice=slice, node=node)
+ if not instances:
+ flavors = Flavor.objects.filter(name="m1.small")
+ if not flavors:
+ raise XOSConfigurationError("No m1.small flavor")
+
+ node =self.pick_node_for_instance()
+ instance = Instance(slice = self.provider_service.slices.all()[0],
+ node = node,
+ image = self.image,
+ creator = self.creator,
+ deployment = node.site_deployment.deployment,
+ flavor = flavors[0])
+ instance.save()
+
+ # Now make the container...
+ container = Container(slice = slice,
+ node = node,
+ docker_image = "andybavier/docker-vcpe",
+ creator = self.creator,
+ no_sync=True)
+ container.save()
+
+ # ... and add the ports for the container
+ # XXX probably should be done in model_policy
+ for network in slice.networks.all():
+ if (network.name.endswith("-nat")):
+ continue
+ port = Port(network = network,
+ container = container)
+ port.save()
+
+ container.no_sync = False
+ container.save()
+
+ try:
+ self.container = container
+ super(TenantWithContainer, self).save()
+ except:
+ container.delete()
+ raise
+
+ def manage_container(self):
+ if self.use_cobm:
+ self.manage_container_on_metal()
+ else:
+ self.manage_container_in_instance()
+
def cleanup_container(self):
if self.instance:
# print "XXX cleanup instance", self.instance
self.instance.delete()
self.instance = None
+ if self.container:
+ # print "XXX cleanup container", self.container
+ self.container.delete()
+ self.container = None
class CoarseTenant(Tenant):
""" TODO: rename "CoarseTenant" --> "StaticTenant" """
diff --git a/xos/helloworld/models.py b/xos/helloworld/models.py
index a657f3a..9bb343e 100644
--- a/xos/helloworld/models.py
+++ b/xos/helloworld/models.py
@@ -11,7 +11,7 @@
class Hello(PlCoreBase):
name = models.CharField(max_length=254,help_text="Salutation e.g. Hello or Bonjour")
- instance_backref = models.ForeignKey(Instance)
+ instance_backref = models.ForeignKey(Instance,related_name="hellos")
class World(PlCoreBase):
name = models.CharField(max_length=254,help_text="Name of planet")
diff --git a/xos/helloworld/view.py b/xos/helloworld/view.py
index b3eec29..7024747 100644
--- a/xos/helloworld/view.py
+++ b/xos/helloworld/view.py
@@ -34,9 +34,9 @@
i.instance_name=None
i.enacted=None
i.save()
- h = Hello(name=hello_name,sliver_backref=i)
- w = World(hello=h,name=world_name)
+ h = Hello(name=hello_name,instance_backref=i)
h.save()
+ w = World(hello=h,name=world_name)
w.save()
t = template.Template(head_template + 'Done. New instance id: %r'%i.pk + self.tail_template)
diff --git a/xos/model-deps b/xos/model-deps
index ea32eb9..59bbe25 100644
--- a/xos/model-deps
+++ b/xos/model-deps
@@ -1,8 +1,6 @@
{
"Slice": [
"Site",
- "Service",
- "ServiceClass",
"User"
],
"ImageDeployments": [
@@ -65,9 +63,6 @@
"Reservation": [
"Slice"
],
- "ServiceResource": [
- "ServiceClass"
- ],
"Instance": [
"Image",
"User",
@@ -79,9 +74,6 @@
"Account": [
"Site"
],
- "ServiceAttribute": [
- "Service"
- ],
"ControllerSlicePrivilege": [
"Controller"
],
@@ -116,9 +108,6 @@
"Controller",
"DashboardView"
],
- "Tag": [
- "Service"
- ],
"Invoice": [
"Account"
],
diff --git a/xos/observers/helloworld/helloworld_config b/xos/observers/helloworld/helloworld_config
index 671af51..e32ee0c 100644
--- a/xos/observers/helloworld/helloworld_config
+++ b/xos/observers/helloworld/helloworld_config
@@ -38,6 +38,7 @@
dependency_graph=/opt/xos/model-deps
logfile=/var/log/xos_backend.log
steps_dir=/opt/xos/observers/helloworld/steps
+applist=helloworld
[gui]
disable_minidashboard=True
diff --git a/xos/observers/helloworld/steps/sync_hello.py b/xos/observers/helloworld/steps/sync_hello.py
index 1fb8c2b..7071ea0 100644
--- a/xos/observers/helloworld/steps/sync_hello.py
+++ b/xos/observers/helloworld/steps/sync_hello.py
@@ -18,7 +18,7 @@
requested_interval=0
def sync_record(self, record):
- instance = record.sliver_backref
+ instance = record.instance_backref
instance.userData="packages:\n - apache2\nruncmd:\n - update-rc.d apache2 enable\n - service apache2 start\nwrite_files:\n- content: Hello %s\n path: /var/www/html/hello.txt"%record.name
instance.save()
diff --git a/xos/openstack_observer/event_loop.py b/xos/openstack_observer/event_loop.py
index 17d5c7a..db7459a 100644
--- a/xos/openstack_observer/event_loop.py
+++ b/xos/openstack_observer/event_loop.py
@@ -27,6 +27,24 @@
from toposort import toposort
from observer.error_mapper import *
from openstack_observer.openstacksyncstep import OpenStackSyncStep
+from observer.steps.sync_object import SyncObject
+
+# Load app models
+
+try:
+ app_module_names = Config().observer_applist
+except AttributeError:
+ app_module_names = []
+
+if (type(app_module_names)!=list):
+ app_module_names=[app_module_names]
+
+app_modules = []
+
+for m in app_module_names:
+ model_path = m+'.models'
+ module = __import__(model_path,fromlist=[m])
+ app_modules.append(module)
debug_mode = False
@@ -166,6 +184,7 @@
provides_dict[m.__name__]=[s.__name__]
step_graph = {}
+ phantom_steps = []
for k,v in self.model_dependency_graph.items():
try:
for source in provides_dict[k]:
@@ -183,7 +202,12 @@
step_graph[source]=[dest]
except KeyError:
if (not provides_dict.has_key(m)):
- step_graph[source]='#%s'%m
+ try:
+ step_graph[source]+=['#%s'%m]
+ except:
+ step_graph[source]=['#%s'%m]
+
+ phantom_steps+=['#%s'%m]
pass
except KeyError:
@@ -196,7 +220,8 @@
pp = pprint.PrettyPrinter(indent=4)
logger.info(pp.pformat(step_graph))
- self.ordered_steps = toposort(self.dependency_graph, map(lambda s:s.__name__,self.sync_steps))
+ self.ordered_steps = toposort(self.dependency_graph, phantom_steps+map(lambda s:s.__name__,self.sync_steps))
+ self.ordered_steps = [i for i in self.ordered_steps if i!='SyncObject']
logger.info("Order of steps=%s" % self.ordered_steps)
@@ -245,15 +270,31 @@
for e in self.ordered_steps:
self.last_deletion_run_times[e]=0
+ def lookup_step_class(self,s):
+ if ('#' in s):
+ return SyncObject
+ else:
+ step = self.step_lookup[s]
+ return step
+
def lookup_step(self,s):
if ('#' in s):
objname = s[1:]
so = SyncObject()
- so.provides=[globals()[objname]]
- so.observes=globals()[objname]
+
+ try:
+ obj = globals()[objname]
+ except:
+ for m in app_modules:
+ if (hasattr(m,objname)):
+ obj = getattr(m,objname)
+
+ so.provides=[obj]
+ so.observes=[obj]
step = so
else:
- step = self.step_lookup[s]
+ step_class = self.step_lookup[s]
+ step = step_class(driver=self.driver,error_map=self.error_mapper)
return step
def save_run_times(self):
@@ -275,7 +316,7 @@
def sync(self, S, deletion):
try:
- step = self.lookup_step(S)
+ step = self.lookup_step_class(S)
start_time=time.time()
logger.info("Starting to work on step %s, deletion=%s" % (step.__name__, str(deletion)))
@@ -324,16 +365,20 @@
self.failed_steps.append(step)
my_status = STEP_STATUS_KO
else:
- sync_step = step(driver=self.driver,error_map=self.error_mapper)
+ sync_step = self.lookup_step(S)
sync_step. __name__= step.__name__
sync_step.dependencies = []
try:
mlist = sync_step.provides
- for m in mlist:
- lst = self.model_dependency_graph[m.__name__]
- nlst = map(lambda(a,b):b,lst)
- sync_step.dependencies.extend(nlst)
+ try:
+ for m in mlist:
+ lst = self.model_dependency_graph[m.__name__]
+ nlst = map(lambda(a,b):b,lst)
+ sync_step.dependencies.extend(nlst)
+ except Exception,e:
+ raise e
+
except KeyError:
pass
sync_step.debug_mode = debug_mode
diff --git a/xos/openstack_observer/steps/sync_container.py b/xos/openstack_observer/steps/sync_container.py
index de4a2ce..0f5dcc4 100644
--- a/xos/openstack_observer/steps/sync_container.py
+++ b/xos/openstack_observer/steps/sync_container.py
@@ -70,6 +70,9 @@
pd["snoop_instance_id"] = instance_port.instance.instance_id
ports.append(pd)
+
+ i = i + 1
+
return ports
def get_extra_attributes(self, o):
@@ -81,6 +84,7 @@
fields["docker_image"] = o.docker_image
fields["username"] = "root"
fields["ports"] = self.get_ports(o)
+ fields["volumes"] = [x.strip() for x in o.volumes.split(",")]
return fields
def sync_fields(self, o, fields):
diff --git a/xos/openstack_observer/steps/sync_container.yaml b/xos/openstack_observer/steps/sync_container.yaml
index a707d0b..e005e58 100644
--- a/xos/openstack_observer/steps/sync_container.yaml
+++ b/xos/openstack_observer/steps/sync_container.yaml
@@ -16,6 +16,10 @@
snoop_instance_mac: {{ port.snoop_instance_mac }}
snoop_instance_id: {{ port.snoop_instance_id }}
{% endfor %}
+ volumes:
+ {% for volume in volumes %}
+ - {{ volume }}
+ {% endfor %}
tasks:
diff --git a/xos/openstack_observer/steps/sync_object.py b/xos/openstack_observer/steps/sync_object.py
index 5e70464..a289c95 100644
--- a/xos/openstack_observer/steps/sync_object.py
+++ b/xos/openstack_observer/steps/sync_object.py
@@ -17,4 +17,4 @@
observes=[] # Caller fills this in
def sync_record(self, r):
- raise Exception('Waiting for Service dependency')
+ raise DeferredException('Waiting for Service dependency: %r'%r)
diff --git a/xos/openstack_observer/syncstep.py b/xos/openstack_observer/syncstep.py
index 7accbfa..21327d7 100644
--- a/xos/openstack_observer/syncstep.py
+++ b/xos/openstack_observer/syncstep.py
@@ -8,6 +8,7 @@
from core.models import *
from django.db import reset_queries
from observer.ansible import *
+from dependency_walker import *
import json
import time
@@ -101,12 +102,26 @@
for dep in self.dependencies:
peer_name = dep[0].lower() + dep[1:] # django names are camelCased with the first letter lower
+ peer_objects=[]
try:
- peer_object = deepgetattr(obj, peer_name)
+ peer_names = plural(peer_name)
+ peer_object_list=[]
+
try:
- peer_objects = peer_object.all()
- except AttributeError:
- peer_objects = [peer_object]
+ peer_object_list.append(deepgetattr(obj, peer_name))
+ except:
+ pass
+
+ try:
+ peer_object_list.append(deepgetattr(obj, peer_names))
+ except:
+ pass
+
+ for peer_object in peer_object_list:
+ try:
+ peer_objects.extend(peer_object.all())
+ except AttributeError:
+ peer_objects.append(peer_object)
except:
peer_objects = []
@@ -174,6 +189,9 @@
pass
def call(self, failed=[], deletion=False):
+ #if ('Instance' in self.__class__.__name__):
+ # pdb.set_trace()
+
pending = self.fetch_pending(deletion)
for o in pending:
diff --git a/xos/openstack_observer/templates/start-container.sh.j2 b/xos/openstack_observer/templates/start-container.sh.j2
index 5656992..dc3b7cb 100644
--- a/xos/openstack_observer/templates/start-container.sh.j2
+++ b/xos/openstack_observer/templates/start-container.sh.j2
@@ -6,11 +6,17 @@
CONTAINER={{ container_name }}
IMAGE={{ docker_image }}
+{% for volume in volumes %}
+DEST_DIR=/var/container_volumes/$CONTAINER/{{ volume }}
+mkdir -p $DEST_DIR
+VOLUME_ARGS="$VOLUME_ARGS -v $DEST_DIR:{{ volume }}"
+{% endfor %}
+
docker inspect $CONTAINER > /dev/null 2>&1
if [ "$?" == 1 ]
then
docker pull $IMAGE
- docker run -d --name=$CONTAINER --privileged=true --net=none $IMAGE
+ docker run -d --name=$CONTAINER --privileged=true --net=none $VOLUME_ARGS $IMAGE
else
docker start $CONTAINER
fi
diff --git a/xos/tosca/custom_types/xos.m4 b/xos/tosca/custom_types/xos.m4
index a661af7..88d8f5f 100644
--- a/xos/tosca/custom_types/xos.m4
+++ b/xos/tosca/custom_types/xos.m4
@@ -136,6 +136,9 @@
dependencies:
type: string
required: false
+ config_network-cfg.json:
+ type: string
+ required: false
tosca.nodes.VCPEService:
description: >
diff --git a/xos/tosca/custom_types/xos.yaml b/xos/tosca/custom_types/xos.yaml
index 9170ecf..4352ef5 100644
--- a/xos/tosca/custom_types/xos.yaml
+++ b/xos/tosca/custom_types/xos.yaml
@@ -154,6 +154,9 @@
dependencies:
type: string
required: false
+ config_network-cfg.json:
+ type: string
+ required: false
tosca.nodes.VCPEService:
description: >
diff --git a/xos/xos_config b/xos/xos_config
index b86d618..c47fac6 100644
--- a/xos/xos_config
+++ b/xos/xos_config
@@ -37,6 +37,7 @@
images_directory=/opt/xos/images
dependency_graph=/opt/xos/model-deps
logfile=/var/log/xos_backend.log
+applist=helloworld
[gui]
disable_minidashboard=True