Merge branch 'master' of https://github.com/open-cloud/xos
diff --git a/xos/configurations/opencloud/Dockerfile b/xos/configurations/opencloud/Dockerfile
index ad85718..5b09507 100644
--- a/xos/configurations/opencloud/Dockerfile
+++ b/xos/configurations/opencloud/Dockerfile
@@ -31,8 +31,8 @@
libyaml-dev \
pkg-config \
supervisor \
- python-crypto
- python-httplib2 \
+ python-crypto \
+ python-httplib2>=0.9.1 \
python-jinja2 \
python-paramiko \
python-pip \
@@ -47,7 +47,7 @@
python-ceilometerclient
RUN pip install \
- django==1.7
+ django==1.7 \
djangorestframework==2.4.4 \
markdown \
pyyaml \
@@ -69,13 +69,14 @@
pygraphviz \
dnslib
+RUN easy_install --upgrade httplib2
+
RUN easy_install \
- django_evolution
+ django_evolution \
python_gflags \
google_api_python_client \
httplib2.ca_certs_locater
-RUN easy_install --upgrade httplib2
# Install custom Ansible
RUN git clone -b release1.8.2 git://github.com/ansible/ansible.git /opt/ansible
@@ -103,7 +104,7 @@
ADD observer.conf /etc/supervisor/conf.d/
# Get XOS
-ADD xos /opt/xos
+RUN git clone git://github.com/open-cloud/xos.git /tmp/xos && mv /tmp/xos/xos /opt/
# Initscript is broken in Ubuntu
#ADD observer-initscript /etc/init.d/xosobserver
@@ -134,7 +135,6 @@
RUN apt-get install -y m4
RUN pip install python-dateutil
RUN bash /opt/xos/tosca/install_tosca.sh
-RUN /usr/bin/python /opt/xos/tosca/run.py padmin@vicci.org ${TOSCA_CONFIG_PATH}
EXPOSE 8000
diff --git a/xos/configurations/opencloud/Makefile b/xos/configurations/opencloud/Makefile
index aba30dc..863f2b7 100644
--- a/xos/configurations/opencloud/Makefile
+++ b/xos/configurations/opencloud/Makefile
@@ -1,8 +1,13 @@
+RUNNING_CONTAINER:=$(shell sudo docker ps|grep "opencloud_server"|awk '{print $$NF}')
+
.PHONY: build
build: ; docker build --rm -t opencloud .
.PHONY: run
-run: ; docker run --rm -d -e TOSCA_CONFIG_PATH=$TOSCA_CONFIG_PATH --name opencloud_server opencloud
+run: ; docker run --rm --name opencloud_server opencloud
+
+.PHONY: runtosca
+runtosca: ; docker exec -it $RUNNING_CONTAINER /usr/bin/python /opt/xos/tosca/run.py padmin@vicci.org $TOSCA_CONFIG_PATH
.PHONY: stop
stop: ; docker stop opencloud_server
diff --git a/xos/configurations/opencloud/ansible-hosts b/xos/configurations/opencloud/ansible-hosts
new file mode 100644
index 0000000..0dd74f1
--- /dev/null
+++ b/xos/configurations/opencloud/ansible-hosts
@@ -0,0 +1,2 @@
+[localhost]
+127.0.0.1
diff --git a/xos/configurations/opencloud/observer.conf b/xos/configurations/opencloud/observer.conf
new file mode 100644
index 0000000..92545eb
--- /dev/null
+++ b/xos/configurations/opencloud/observer.conf
@@ -0,0 +1,2 @@
+[program:observer]
+command=python /opt/xos/xos-observer.py
diff --git a/xos/helloworld/view.py b/xos/helloworld/view.py
new file mode 100644
index 0000000..b3eec29
--- /dev/null
+++ b/xos/helloworld/view.py
@@ -0,0 +1,58 @@
+from django.http import HttpResponse
+from django.views.generic import TemplateView, View
+from django import template
+from monitor import driver
+from core.models import *
+from helloworld.models import *
+import json
+import os
+import time
+import tempfile
+
+class HelloWorldView(TemplateView):
+ head_template = r"""{% extends "admin/dashboard/dashboard_base.html" %}
+ {% load admin_static %}
+ {% block content %}
+ """
+
+ tail_template = r"{% endblock %}"
+
+ def get(self, request, name="root", *args, **kwargs):
+ head_template = self.head_template
+ tail_template = self.tail_template
+
+ try:
+ hello_name = request.GET['hello_name']
+ world_name = request.GET['world_name']
+ instance_id_str = request.GET['instance_id']
+ instance_id = int(instance_id_str)
+
+ i = Instance.objects.get(pk=instance_id)
+ i.pk=None
+ i.userData=None
+ i.instance_id=None
+ 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.save()
+ w.save()
+
+ t = template.Template(head_template + 'Done. New instance id: %r'%i.pk + self.tail_template)
+ except KeyError:
+ html = """<form>
+ Hello string: <input type="text" name="hello_name" placeholder="Planet"><br>
+ World string: <input type="text" name="world_name" placeholder="Earth"><br>
+ Id of instance to copy: <input type="text" name="instance_id" placeholder="3"><br>
+ <input type="submit" value="Submit">
+ </form>"""
+
+ t = template.Template(head_template + html + self.tail_template)
+
+ response_kwargs = {}
+ response_kwargs.setdefault('content_type', self.content_type)
+ return self.response_class(
+ request = request,
+ template = t,
+ **response_kwargs)
diff --git a/xos/observers/hello_world/run.sh b/xos/observers/hello_world/run.sh
deleted file mode 100755
index 1107a7a..0000000
--- a/xos/observers/hello_world/run.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-#if [[ ! -e ./hpc-backend.py ]]; then
-# ln -s ../xos-observer.py hpc-backend.py
-#fi
-
-export XOS_DIR=/opt/xos
-python helloworld-observer.py -C $XOS_DIR/observers/hello_world/helloworld_config
diff --git a/xos/observers/hello_world/helloworld-observer.py b/xos/observers/helloworld/helloworld-observer.py
similarity index 100%
rename from xos/observers/hello_world/helloworld-observer.py
rename to xos/observers/helloworld/helloworld-observer.py
diff --git a/xos/observers/hello_world/helloworld_config b/xos/observers/helloworld/helloworld_config
similarity index 94%
rename from xos/observers/hello_world/helloworld_config
rename to xos/observers/helloworld/helloworld_config
index 97248ae..671af51 100644
--- a/xos/observers/hello_world/helloworld_config
+++ b/xos/observers/helloworld/helloworld_config
@@ -37,7 +37,7 @@
images_directory=/opt/xos/images
dependency_graph=/opt/xos/model-deps
logfile=/var/log/xos_backend.log
-steps_dir=/opt/xos/observers/hello_world/steps
+steps_dir=/opt/xos/observers/helloworld/steps
[gui]
disable_minidashboard=True
diff --git a/xos/observers/hello_world/model-deps b/xos/observers/helloworld/model-deps
similarity index 100%
rename from xos/observers/hello_world/model-deps
rename to xos/observers/helloworld/model-deps
diff --git a/xos/observers/hello_world/nohup.out b/xos/observers/helloworld/nohup.out
similarity index 100%
rename from xos/observers/hello_world/nohup.out
rename to xos/observers/helloworld/nohup.out
diff --git a/xos/observers/helloworld/run.sh b/xos/observers/helloworld/run.sh
new file mode 100755
index 0000000..f56ffe3
--- /dev/null
+++ b/xos/observers/helloworld/run.sh
@@ -0,0 +1,6 @@
+#if [[ ! -e ./hpc-backend.py ]]; then
+# ln -s ../xos-observer.py hpc-backend.py
+#fi
+
+export XOS_DIR=/opt/xos
+python helloworld-observer.py -C $XOS_DIR/observers/helloworld/helloworld_config
diff --git a/xos/observers/hello_world/start.sh b/xos/observers/helloworld/start.sh
similarity index 100%
rename from xos/observers/hello_world/start.sh
rename to xos/observers/helloworld/start.sh
diff --git a/xos/observers/hello_world/steps/sync_hello.py b/xos/observers/helloworld/steps/sync_hello.py
similarity index 65%
rename from xos/observers/hello_world/steps/sync_hello.py
rename to xos/observers/helloworld/steps/sync_hello.py
index f59ec5c..1fb8c2b 100644
--- a/xos/observers/hello_world/steps/sync_hello.py
+++ b/xos/observers/helloworld/steps/sync_hello.py
@@ -18,7 +18,9 @@
requested_interval=0
def sync_record(self, record):
- open('/tmp/hello-synchronizer','w').write(record.name)
+ instance = record.sliver_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()
def delete_record(self, m):
return
diff --git a/xos/observers/hello_world/steps/sync_world.py b/xos/observers/helloworld/steps/sync_world.py
similarity index 100%
rename from xos/observers/hello_world/steps/sync_world.py
rename to xos/observers/helloworld/steps/sync_world.py
diff --git a/xos/observers/hello_world/stop.sh b/xos/observers/helloworld/stop.sh
similarity index 100%
rename from xos/observers/hello_world/stop.sh
rename to xos/observers/helloworld/stop.sh
diff --git a/xos/openstack_observer/steps/sync_controller_networks.py b/xos/openstack_observer/steps/sync_controller_networks.py
index 1e7805f..ef238ee 100644
--- a/xos/openstack_observer/steps/sync_controller_networks.py
+++ b/xos/openstack_observer/steps/sync_controller_networks.py
@@ -69,7 +69,7 @@
if (controller_network.network.template.name!='Private'):
logger.info("skipping network controller %s because it is not private" % controller_network)
# We only sync private networks
- return
+ return SyncStep.SYNC_WITHOUT_RUNNING
if not controller_network.controller.admin_user:
logger.info("controller %r has no admin_user, skipping" % controller_network.controller)
diff --git a/xos/openstack_observer/steps/sync_instances.py b/xos/openstack_observer/steps/sync_instances.py
index 7aa4bb7..1209448 100644
--- a/xos/openstack_observer/steps/sync_instances.py
+++ b/xos/openstack_observer/steps/sync_instances.py
@@ -56,10 +56,12 @@
controller=instance.node.site_deployment.controller)
for controller_network in controller_networks:
+
+ # Lenient exception - causes slow backoff
if controller_network.network.template.visibility == 'private' and \
controller_network.network.template.translation == 'none':
if not controller_network.net_id:
- raise Exception("Private Network %s has no id; Try again later" % controller_network.network.name)
+ raise DeferredException("Private Network %s has no id; Try again later" % controller_network.network.name)
nics.append(controller_network.net_id)
# now include network template
@@ -108,7 +110,7 @@
userData = self.get_userdata(instance, pubkeys)
if instance.userData:
- userData = instance.userData
+ userData += instance.userData
controller = instance.node.site_deployment.controller
fields = {'endpoint':controller.auth_url,
diff --git a/xos/openstack_observer/syncstep.py b/xos/openstack_observer/syncstep.py
index 66225d0..7accbfa 100644
--- a/xos/openstack_observer/syncstep.py
+++ b/xos/openstack_observer/syncstep.py
@@ -45,6 +45,12 @@
psmodel Model name the step synchronizes
dependencies list of names of models that must be synchronized first if the current model depends on them
"""
+
+ # map_sync_outputs can return this value to cause a step to be marked
+ # successful without running ansible. Used for sync_network_controllers
+ # on nat networks.
+ SYNC_WITHOUT_RUNNING = "sync_without_running"
+
slow=False
def get_prop(self, prop):
try:
@@ -128,6 +134,8 @@
pass
tenant_fields = self.map_sync_inputs(o)
+ if tenant_fields == SyncStep.SYNC_WITHOUT_RUNNING:
+ return
main_objs=self.observes
if (type(main_objs) is list):
main_objs=main_objs[0]
diff --git a/xos/tosca/custom_types/xos.m4 b/xos/tosca/custom_types/xos.m4
index 81d1333..00805e7 100644
--- a/xos/tosca/custom_types/xos.m4
+++ b/xos/tosca/custom_types/xos.m4
@@ -12,7 +12,11 @@
no-create:
type: boolean
default: false
- description: Do not allow Tosca to create this object)
+ description: Do not allow Tosca to create this object
+ no-update:
+ type: boolean
+ default: false
+ description: Do not allow Tosca to update this object)
# Service
define(xos_base_service_caps,
scalable:
@@ -59,7 +63,7 @@
service_specific_id:
type: string
required: false
- description: Service specific ID, opaque to XOS but meaningful to service)
+ description: Service specific ID opaque to XOS but meaningful to service)
define(xos_base_tenant_props,
kind:
type: string
@@ -68,7 +72,7 @@
service_specific_id:
type: string
required: false
- description: Service specific ID, opaque to XOS but meaningful to service)
+ description: Service specific ID opaque to XOS but meaningful to service)
# end m4 macros
#
@@ -410,6 +414,7 @@
controller:
type: tosca.capabilities.xos.Controller
properties:
+ xos_base_props
backend_type:
type: string
required: false
@@ -447,29 +452,30 @@
site:
type: tosca.capabilities.xos.Site
properties:
- display_name:
- type: string
- required: false
- description: Name of the site.
- site_url:
- type: string
- required: false
- description: URL of site web page.
- enabled:
- type: boolean
- default: true
- hosts_nodes:
- type: boolean
- default: true
- description: If True, then this site hosts nodes where Instances may be instantiated.
- hosts_users:
- type: boolean
- default: true
- description: If True, then this site hosts users who may use XOS.
- is_public:
- type: boolean
- default: true
- # location, longitude, latitude
+ xos_base_props
+ display_name:
+ type: string
+ required: false
+ description: Name of the site.
+ site_url:
+ type: string
+ required: false
+ description: URL of site web page.
+ enabled:
+ type: boolean
+ default: true
+ hosts_nodes:
+ type: boolean
+ default: true
+ description: If True, then this site hosts nodes where Instances may be instantiated.
+ hosts_users:
+ type: boolean
+ default: true
+ description: If True, then this site hosts users who may use XOS.
+ is_public:
+ type: boolean
+ default: true
+ # location, longitude, latitude
tosca.nodes.Slice:
derived_from: tosca.nodes.Root
@@ -480,6 +486,7 @@
slice:
type: tosca.capabilities.xos.Slice
properties:
+ xos_base_props
enabled:
type: boolean
default: true
@@ -501,7 +508,9 @@
description: >
An XOS Node. Nodes are physical machines that host virtual machines
and/or containers.
- capability:
+ properties:
+ xos_base_props
+ capabilities:
node:
type: tosca.capabilities.xos.Node
diff --git a/xos/tosca/custom_types/xos.yaml b/xos/tosca/custom_types/xos.yaml
index 9e25754..2a904c1 100644
--- a/xos/tosca/custom_types/xos.yaml
+++ b/xos/tosca/custom_types/xos.yaml
@@ -193,7 +193,7 @@
service_specific_id:
type: string
required: false
- description: Service specific ID
+ description: Service specific ID opaque to XOS but meaningful to service
tosca.nodes.CORDSubscriber:
derived_from: tosca.nodes.Root
@@ -212,7 +212,7 @@
service_specific_id:
type: string
required: false
- description: Service specific ID
+ description: Service specific ID opaque to XOS but meaningful to service
firewall_enable:
type: boolean
default: false
@@ -262,7 +262,7 @@
service_specific_id:
type: string
required: false
- description: Service specific ID
+ description: Service specific ID opaque to XOS but meaningful to service
vlan_id:
type: string
required: false
@@ -460,6 +460,10 @@
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
accessControl:
type: string
default: allow all
@@ -499,6 +503,18 @@
controller:
type: tosca.capabilities.xos.Controller
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
backend_type:
type: string
required: false
@@ -536,29 +552,41 @@
site:
type: tosca.capabilities.xos.Site
properties:
- display_name:
- type: string
- required: false
- description: Name of the site.
- site_url:
- type: string
- required: false
- description: URL of site web page.
- enabled:
- type: boolean
- default: true
- hosts_nodes:
- type: boolean
- default: true
- description: If True, then this site hosts nodes where Instances may be instantiated.
- hosts_users:
- type: boolean
- default: true
- description: If True, then this site hosts users who may use XOS.
- is_public:
- type: boolean
- default: true
- # location, longitude, latitude
+ 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
+ display_name:
+ type: string
+ required: false
+ description: Name of the site.
+ site_url:
+ type: string
+ required: false
+ description: URL of site web page.
+ enabled:
+ type: boolean
+ default: true
+ hosts_nodes:
+ type: boolean
+ default: true
+ description: If True, then this site hosts nodes where Instances may be instantiated.
+ hosts_users:
+ type: boolean
+ default: true
+ description: If True, then this site hosts users who may use XOS.
+ is_public:
+ type: boolean
+ default: true
+ # location, longitude, latitude
tosca.nodes.Slice:
derived_from: tosca.nodes.Root
@@ -569,6 +597,18 @@
slice:
type: tosca.capabilities.xos.Slice
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
enabled:
type: boolean
default: true
@@ -590,7 +630,20 @@
description: >
An XOS Node. Nodes are physical machines that host virtual machines
and/or containers.
- capability:
+ 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
+ capabilities:
node:
type: tosca.capabilities.xos.Node
diff --git a/xos/tosca/resources/controller.py b/xos/tosca/resources/controller.py
index da4ed64..9a20ea5 100644
--- a/xos/tosca/resources/controller.py
+++ b/xos/tosca/resources/controller.py
@@ -44,6 +44,10 @@
if obj.controllersite.exists():
self.info("Controller %s has active sites; skipping delete" % obj.name)
return
+ for sd in obj.sitedeployments.all():
+ if sd.nodes.exists():
+ self.info("Controller %s has active nodes; skipping delete" % obj.name)
+ return
super(XOSController, self).delete(obj)
diff --git a/xos/tosca/resources/deployment.py b/xos/tosca/resources/deployment.py
index 152b1f9..ed6734c 100644
--- a/xos/tosca/resources/deployment.py
+++ b/xos/tosca/resources/deployment.py
@@ -51,13 +51,13 @@
self.postprocess_privileges(DeploymentRole, DeploymentPrivilege, rolemap, obj, "deployment")
def delete(self, obj):
- if self.get_property("no-delete"):
- self.info("Deployment %s is marked no-delete")
- return
-
if obj.sites.exists():
self.info("Deployment %s has active sites; skipping delete" % obj.name)
return
+ for sd in obj.sitedeployments.all():
+ if sd.nodes.exists():
+ self.info("Deployment %s has active nodes; skipping delete" % obj.name)
+ return
#if obj.nodes.exists():
# self.info("Deployment %s has active nodes; skipping delete" % obj.name)
# return
diff --git a/xos/tosca/resources/xosresource.py b/xos/tosca/resources/xosresource.py
index 62f18db..3553ab1 100644
--- a/xos/tosca/resources/xosresource.py
+++ b/xos/tosca/resources/xosresource.py
@@ -60,6 +60,12 @@
def get_property(self, name):
return self.nodetemplate.get_property_value(name)
+ def get_property_default(self, name, default=None):
+ props = self.nodetemplate.get_properties()
+ if props and name in props.keys():
+ return props[name].value
+ return default
+
def get_xos_object(self, cls, throw_exception=True, **kwargs):
objs = cls.objects.filter(**kwargs)
if not objs:
@@ -80,12 +86,21 @@
def create_or_update(self):
existing_objs = self.get_existing_objs()
if existing_objs:
- self.info("%s %s already exists" % (self.get_model_class_name(), self.nodetemplate.name))
- self.update(existing_objs[0])
+ if self.get_property_default("no-update", False):
+ self.info("%s %s already exists. Skipping update due to 'no-update' property" % (self.get_model_class_name(), self.nodetemplate.name))
+ else:
+ self.info("%s %s already exists" % (self.get_model_class_name(), self.nodetemplate.name))
+ self.update(existing_objs[0])
else:
- self.create()
+ if self.get_property_default("no-create", False):
+ self.info("%s %s does not exist, but 'no-create' is specified" % (self.get_model_class_name(), self.nodetemplate.name))
+ else:
+ self.create()
def can_delete(self, obj):
+ if self.get_property_default("no-delete",False):
+ self.info("%s %s is marked 'no-delete'. Skipping delete." % (self.get_model_class_name(), self.nodetemplate.name))
+ return False
return True
def postprocess_privileges(self, roleclass, privclass, rolemap, obj, toFieldName):
diff --git a/xos/tosca/tests/controllertest.py b/xos/tosca/tests/controllertest.py
index 5746ada..2b7ba55 100644
--- a/xos/tosca/tests/controllertest.py
+++ b/xos/tosca/tests/controllertest.py
@@ -5,7 +5,9 @@
class ControllerTest(BaseToscaTest):
tests = ["create_controller_minimal",
"create_controller_maximal",
- "destroy_controller"]
+ "create_controller_nocreate",
+ "destroy_controller",
+ "destroy_controller_nodelete"]
def cleanup(self):
self.try_to_delete(Controller, name="testcon")
@@ -53,6 +55,45 @@
domain="mydomain",
deployment=dep)
+ def create_controller_nocreate(self):
+ self.assert_noobj(Controller, "testcon")
+ self.execute(self.get_base_templates() +
+ self.make_nodetemplate("testcon", "tosca.nodes.Controller",
+ reqs=[("testdep", "tosca.relationships.ControllerDeployment")],
+ props={"no-create": True}))
+ dep = self.assert_obj(Deployment, "testdep")
+ self.assert_noobj(Controller, "testcon")
+
+ def update_controller(self):
+ self.assert_noobj(Controller, "testcon")
+ self.execute(self.get_base_templates() +
+ self.make_nodetemplate("testcon", "tosca.nodes.Controller",
+ reqs=[("testdep", "tosca.relationships.ControllerDeployment")]))
+ dep = self.assert_obj(Deployment, "testdep")
+ orig_con = self.assert_obj(Controller, "testcon",
+ backend_type="",
+ version="",
+ auth_url=None,
+ admin_user=None,
+ admin_password=None,
+ admin_tenant=None,
+ domain=None,
+ deployment=dep)
+ self.execute(self.get_base_templates() +
+ self.make_nodetemplate("testcon", "tosca.nodes.Controller",
+ reqs=[("testdep", "tosca.relationships.ControllerDeployment")],
+ props={"version": "1.1"}))
+ con = self.assert_obj(Controller, "testcon",
+ backend_type="",
+ version="1.1",
+ auth_url=None,
+ admin_user=None,
+ admin_password=None,
+ admin_tenant=None,
+ domain=None,
+ deployment=dep)
+ assert(orig_con.id == con.id)
+
def destroy_controller(self):
self.assert_noobj(Controller, "testcon")
self.execute(self.get_base_templates() +
@@ -64,6 +105,24 @@
reqs=[("testdep", "tosca.relationships.ControllerDeployment")]))
self.assert_noobj(Controller, "testcon")
+ def destroy_controller_nodelete(self):
+ self.assert_noobj(Controller, "testcon")
+ self.execute(self.get_base_templates() +
+ self.make_nodetemplate("testcon", "tosca.nodes.Controller",
+ reqs=[("testdep", "tosca.relationships.ControllerDeployment")]))
+ orig_con = self.assert_obj(Controller, "testcon")
+ # NOTE: Had to specify no-delete on the deployment as well, otherwise
+ # the deployment deletion would cause the controller to be deleted
+ # as well. I'm thinking this is as it should be, but it's a little
+ # counter-inutitive.
+ self.destroy(self.make_nodetemplate("testdep", "tosca.nodes.Deployment",
+ props={"no-delete": True}) +
+ self.make_nodetemplate("testcon", "tosca.nodes.Controller",
+ reqs=[("testdep", "tosca.relationships.ControllerDeployment")],
+ props={"no-delete": True}))
+ con = self.assert_obj(Controller, "testcon")
+ assert(orig_con.id == con.id)
+
if __name__ == "__main__":
ControllerTest()
diff --git a/xos/tosca/tests/deploymenttest.py b/xos/tosca/tests/deploymenttest.py
index 0156613..91caf75 100644
--- a/xos/tosca/tests/deploymenttest.py
+++ b/xos/tosca/tests/deploymenttest.py
@@ -10,6 +10,9 @@
"create_deployment_one_image",
"create_deployment_two_images",
"create_deployment_privilege",
+ "create_deployment_nocreate",
+ "update_deployment",
+ "update_deployment_noupdate",
"destroy_deployment",
"destroy_deployment_nodelete"
]
@@ -88,6 +91,35 @@
dps = DeploymentPrivilege.objects.filter(user=user, deployment=dep)
assert(len(dps) == 1)
+ def create_deployment_nocreate(self):
+ self.assert_noobj(Deployment, "testdep")
+ self.execute(self.make_nodetemplate("testdep", "tosca.nodes.Deployment",
+ props={"no-create": True}))
+ self.assert_noobj(Deployment, "testdep")
+
+ def update_deployment(self):
+ self.assert_noobj(Deployment, "testdep")
+ self.execute(self.make_nodetemplate("testdep", "tosca.nodes.Deployment"))
+ orig_dep = self.assert_obj(Deployment, "testdep",
+ accessControl="allow all")
+ self.execute(self.make_nodetemplate("testdep", "tosca.nodes.Deployment",
+ props={"accessControl": "allow padmin@vicci.org"}))
+ dep = self.assert_obj(Deployment, "testdep",
+ accessControl="allow padmin@vicci.org")
+ assert(dep.id == orig_dep.id)
+
+ def update_deployment_noupdate(self):
+ self.assert_noobj(Deployment, "testdep")
+ self.execute(self.make_nodetemplate("testdep", "tosca.nodes.Deployment"))
+ orig_dep = self.assert_obj(Deployment, "testdep",
+ accessControl="allow all")
+ self.execute(self.make_nodetemplate("testdep", "tosca.nodes.Deployment",
+ props={"accessControl": "allow padmin@vicci.org",
+ "no-update": True}))
+ dep = self.assert_obj(Deployment, "testdep",
+ accessControl="allow all")
+ assert(dep.id == orig_dep.id)
+
def destroy_deployment(self):
self.assert_noobj(Deployment, "testdep")
self.execute(self.make_nodetemplate("testdep", "tosca.nodes.Deployment"))
diff --git a/xos/tosca/tests/nodetest.py b/xos/tosca/tests/nodetest.py
index d49dab1..76c56a8 100644
--- a/xos/tosca/tests/nodetest.py
+++ b/xos/tosca/tests/nodetest.py
@@ -4,7 +4,9 @@
class NodeTest(BaseToscaTest):
tests = ["create_node_minimal",
+ "create_node_nocreate",
"destroy_node",
+ "destroy_node_nodelete",
]
def cleanup(self):
@@ -43,7 +45,18 @@
self.make_nodetemplate("testnode", "tosca.nodes.Node",
reqs=[("testsite", "tosca.relationships.MemberOfSite"),
("testdep", "tosca.relationships.MemberOfDeployment")]))
- self.assert_obj(Node, "testnode")
+ node = self.assert_obj(Node, "testnode")
+ assert(node.site_deployment is not None)
+ assert(node.site is not None)
+
+ def create_node_nocreate(self):
+ self.assert_noobj(Node, "testnode")
+ self.execute(self.get_base_templates() +
+ self.make_nodetemplate("testnode", "tosca.nodes.Node",
+ reqs=[("testsite", "tosca.relationships.MemberOfSite"),
+ ("testdep", "tosca.relationships.MemberOfDeployment")],
+ props={"no-create": True}))
+ self.assert_noobj(Node, "testnode")
def destroy_node(self):
self.assert_noobj(Node, "testnode")
@@ -58,6 +71,20 @@
("testdep", "tosca.relationships.MemberOfDeployment")]))
self.assert_noobj(Node, "testnode")
+ def destroy_node_nodelete(self):
+ self.assert_noobj(Node, "testnode")
+ self.execute(self.get_base_templates() +
+ self.make_nodetemplate("testnode", "tosca.nodes.Node",
+ reqs=[("testsite", "tosca.relationships.MemberOfSite"),
+ ("testdep", "tosca.relationships.MemberOfDeployment")]))
+ self.assert_obj(Node, "testnode")
+ self.destroy(self.get_base_templates() +
+ self.make_nodetemplate("testnode", "tosca.nodes.Node",
+ reqs=[("testsite", "tosca.relationships.MemberOfSite"),
+ ("testdep", "tosca.relationships.MemberOfDeployment")],
+ props={"no-delete": True}))
+ self.assert_obj(Node, "testnode")
+
if __name__ == "__main__":
NodeTest()
diff --git a/xos/tosca/tests/sitetest.py b/xos/tosca/tests/sitetest.py
index c9a4743..5321159 100644
--- a/xos/tosca/tests/sitetest.py
+++ b/xos/tosca/tests/sitetest.py
@@ -7,7 +7,11 @@
"create_site_privilege_tech",
"create_site_privilege_admin",
"create_site_privilege_pi",
+ "create_site_nocreate",
+ "update_site",
+ "update_site_noupdate",
"destroy_site",
+ "destroy_site_nodelete"
]
def cleanup(self):
@@ -60,6 +64,31 @@
assert(len(sps) == 1)
assert(sps[0].role.role == "pi")
+ def create_site_nocreate(self):
+ self.assert_noobj(Site, "testsite")
+ self.execute(self.make_nodetemplate("testsite", "tosca.nodes.Site",
+ props={"no-create": True}))
+ site = self.assert_noobj(Site, "testsite")
+
+ def update_site(self):
+ self.assert_noobj(Site, "testsite")
+ self.execute(self.make_nodetemplate("testsite", "tosca.nodes.Site"))
+ orig_site = self.assert_obj(Site, "testsite", site_url=None)
+ self.execute(self.make_nodetemplate("testsite", "tosca.nodes.Site",
+ props={"site_url": "http://foo.com/"}))
+ site = self.assert_obj(Site, "testsite", site_url="http://foo.com/")
+ assert(orig_site.id == site.id)
+
+ def update_site_noupdate(self):
+ self.assert_noobj(Site, "testsite")
+ self.execute(self.make_nodetemplate("testsite", "tosca.nodes.Site"))
+ orig_site = self.assert_obj(Site, "testsite", site_url=None)
+ self.execute(self.make_nodetemplate("testsite", "tosca.nodes.Site",
+ props={"site_url": "http://foo.com/",
+ "no-update": True}))
+ site = self.assert_obj(Site, "testsite", site_url=None)
+ assert(orig_site.id == site.id)
+
def destroy_site(self):
self.assert_noobj(Site, "testsite")
self.execute(self.make_nodetemplate("testsite", "tosca.nodes.Site"))
@@ -67,6 +96,14 @@
self.destroy(self.make_nodetemplate("testsite", "tosca.nodes.Site"))
self.assert_noobj(Site, "testsite")
+ def destroy_site_nodelete(self):
+ self.assert_noobj(Site, "testsite")
+ self.execute(self.make_nodetemplate("testsite", "tosca.nodes.Site"))
+ site = self.assert_obj(Site, "testsite")
+ self.destroy(self.make_nodetemplate("testsite", "tosca.nodes.Site",
+ props={"no-delete": True}))
+ self.assert_obj(Site, "testsite")
+
if __name__ == "__main__":
SiteTest()
diff --git a/xos/tosca/tests/slicetest.py b/xos/tosca/tests/slicetest.py
index 315f862..98de4e6 100644
--- a/xos/tosca/tests/slicetest.py
+++ b/xos/tosca/tests/slicetest.py
@@ -6,7 +6,11 @@
tests = ["create_slice_minimal",
"create_slice_maximal",
"create_slice_privilege",
- "destroy_slice"]
+ "create_slice_nocreate",
+ "update_slice",
+ "update_slice_noupdate",
+ "destroy_slice",
+ "destroy_slice_nodelete"]
def cleanup(self):
self.try_to_delete(Slice, name="testsite_testslice")
@@ -43,6 +47,41 @@
dps = SlicePrivilege.objects.filter(user=user, slice=slice)
assert(len(dps) == 1)
+ def create_slice_nocreate(self):
+ self.assert_noobj(Slice, "testsite_testslice")
+ self.execute(self.get_base_templates() +
+ self.make_nodetemplate("testsite_testslice", "tosca.nodes.Slice",
+ reqs=[("testsite", "tosca.relationships.MemberOfSite")],
+ props={"no-create": True}))
+ self.assert_noobj(Slice, "testsite_testslice")
+
+ def update_slice(self):
+ self.assert_noobj(Slice, "testsite_testslice")
+ self.execute(self.get_base_templates() +
+ self.make_nodetemplate("testsite_testslice", "tosca.nodes.Slice",
+ reqs=[("testsite", "tosca.relationships.MemberOfSite")]))
+ orig_slice = self.assert_obj(Slice, "testsite_testslice", enabled=True, description="", slice_url="", max_instances=10)
+ self.execute(self.get_base_templates() +
+ self.make_nodetemplate("testsite_testslice", "tosca.nodes.Slice",
+ reqs=[("testsite", "tosca.relationships.MemberOfSite")],
+ props={"description": "foo"}))
+ slice = self.assert_obj(Slice, "testsite_testslice", enabled=True, description="foo", slice_url="", max_instances=10)
+ assert(orig_slice.id == slice.id)
+
+ def update_slice_noupdate(self):
+ self.assert_noobj(Slice, "testsite_testslice")
+ self.execute(self.get_base_templates() +
+ self.make_nodetemplate("testsite_testslice", "tosca.nodes.Slice",
+ reqs=[("testsite", "tosca.relationships.MemberOfSite")]))
+ orig_slice = self.assert_obj(Slice, "testsite_testslice", enabled=True, description="", slice_url="", max_instances=10)
+ self.execute(self.get_base_templates() +
+ self.make_nodetemplate("testsite_testslice", "tosca.nodes.Slice",
+ reqs=[("testsite", "tosca.relationships.MemberOfSite")],
+ props={"description": "foo",
+ "no-update": True}))
+ slice = self.assert_obj(Slice, "testsite_testslice", enabled=True, description="", slice_url="", max_instances=10)
+ assert(orig_slice.id == slice.id)
+
def destroy_slice(self):
self.assert_noobj(Slice, "testsite_testslice")
self.execute(self.get_base_templates() +
@@ -54,6 +93,19 @@
reqs=[("testsite", "tosca.relationships.MemberOfSite")]))
self.assert_noobj(Slice, "testsite_testslice")
+ def destroy_slice_nodelete(self):
+ self.assert_noobj(Slice, "testsite_testslice")
+ self.execute(self.get_base_templates() +
+ self.make_nodetemplate("testsite_testslice", "tosca.nodes.Slice",
+ reqs=[("testsite", "tosca.relationships.MemberOfSite")]))
+ orig_slice = self.assert_obj(Slice, "testsite_testslice", enabled=True, description="", slice_url="", max_instances=10)
+ self.destroy(self.get_base_templates() +
+ self.make_nodetemplate("testsite_testslice", "tosca.nodes.Slice",
+ reqs=[("testsite", "tosca.relationships.MemberOfSite")],
+ props={"no-delete": True}))
+ slice = self.assert_obj(Slice, "testsite_testslice", enabled=True, description="", slice_url="", max_instances=10)
+ assert(slice.id == orig_slice.id)
+
if __name__ == "__main__":
SliceTest()
diff --git a/xos/xos/urls.py b/xos/xos/urls.py
index 0adf32d..6ba98d8 100644
--- a/xos/xos/urls.py
+++ b/xos/xos/urls.py
@@ -8,6 +8,7 @@
from core.views.legacyapi import LegacyXMLRPC
from core.views.services import ServiceGridView, ServiceGraphView
+from helloworld.view import *
#from core.views.analytics import AnalyticsAjaxView
from core.models import *
from rest_framework import generics
@@ -27,6 +28,7 @@
# Examples:
url(r'^stats', 'core.views.stats.Stats', name='stats'),
url(r'^observer', 'core.views.observer.Observer', name='observer'),
+ url(r'^helloworld', HelloWorldView.as_view(), name='helloWorld'),
url(r'^serviceGrid', ServiceGridView.as_view(), name='serviceGrid'),
url(r'^serviceGraph.png', ServiceGraphView.as_view(), name='serviceGraph'),
url(r'^hpcConfig', 'core.views.hpc_config.HpcConfig', name='hpcConfig'),