resolve merge conflicts
diff --git a/containers/onboarding_synchronizer/Dockerfile b/containers/onboarding_synchronizer/Dockerfile
new file mode 100644
index 0000000..967e234
--- /dev/null
+++ b/containers/onboarding_synchronizer/Dockerfile
@@ -0,0 +1,40 @@
+FROM xosproject/xos-synchronizer-openstack
+
+# Install docker-in-docker (dind). See https://hub.docker.com/_/docker/. The docker git repo
+# currently only has 1.10 and 1.11, but it's possible to get the dockerfiles for earlier
+# versions by using:
+# docker pull centurylink/dockerfile-from-image
+# alias dfimage="docker run -v /var/run/docker.sock:/var/run/docker.sock --rm centurylink/dockerfile-from-image"
+# dgimage <name of image>
+
+# This container must be started in privileged mode.
+
+RUN apt-get install -y curl
+# iptables
+ENV DOCKER_BUCKET=get.docker.com
+ENV DOCKER_VERSION=1.8.3
+ENV DOCKER_SHA256=f024bc65c45a3778cf07213d26016075e8172de8f6e4b5702bedde06c241650f
+RUN curl -fSL "https://${DOCKER_BUCKET}/builds/Linux/x86_64/docker-$DOCKER_VERSION" -o /usr/local/bin/docker && echo "${DOCKER_SHA256} /usr/local/bin/docker" | sha256sum -c - && chmod +x /usr/local/bin/docker
+
+# XXX uncomment the following 6 lines to run docker-in-docker
+# comment them out if using the docker socket in a volume instead
+#ENV DIND_COMMIT=3b5fac462d21ca164b3778647420016315289034
+#RUN wget "https://raw.githubusercontent.com/docker/docker/${DIND_COMMIT}/hack/dind" -O /usr/local/bin/dind && chmod +x /usr/local/bin/dind
+#COPY start-dockerd.sh /usr/local/bin/
+#VOLUME /var/lib/docker
+#EXPOSE 2375
+#ENTRYPOINT ["start-dockerd.sh"]
+
+# Instead of using docker-in-docker, we can just attach ourselves
+# to the docker socket via a volume in the docker-compose:
+# - /var/run/docker.sock:/var/run/docker.sock
+# This is more convenient, allowing us to build directly into our
+# parent's docker build system, making the images available for
+# instantiation on the parent.
+
+# Now install docker-compose
+
+RUN bash -c "curl -L https://github.com/docker/compose/releases/download/1.5.2/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose"
+RUN chmod +x /usr/local/bin/docker-compose
+
+CMD update-ca-certificates && /usr/bin/supervisord -c /etc/supervisor/conf.d/synchronizer.conf
diff --git a/containers/onboarding_synchronizer/Makefile b/containers/onboarding_synchronizer/Makefile
new file mode 100644
index 0000000..6532196
--- /dev/null
+++ b/containers/onboarding_synchronizer/Makefile
@@ -0,0 +1,15 @@
+IMAGE_NAME:=xosproject/xos-synchronizer-onboarding
+CONTAINER_NAME:=xos-synchronizer
+NO_DOCKER_CACHE?=false
+
+.PHONY: build
+build: ; sudo docker build --no-cache=${NO_DOCKER_CACHE} --rm -t ${IMAGE_NAME} .
+
+.PHONY: run
+run: ; sudo docker run -d --name ${CONTAINER_NAME} -v /usr/local/share/ca-certificates:/usr/local/share/ca-certificates:ro ${IMAGE_NAME}
+
+.PHONY: stop
+stop: ; sudo docker stop ${CONTAINER_NAME}
+
+.PHONY: rm
+rm: ; sudo docker rm ${CONTAINER_NAME}
diff --git a/containers/onboarding_synchronizer/start-dockerd.sh b/containers/onboarding_synchronizer/start-dockerd.sh
new file mode 100755
index 0000000..bb97341
--- /dev/null
+++ b/containers/onboarding_synchronizer/start-dockerd.sh
@@ -0,0 +1,3 @@
+#! /bin/bash
+
+docker daemon --host=unix:///var/run/docker.sock --host=tcp://0.0.0.0:2375 --storage-driver=aufs
diff --git a/xos/api/utility/onboarding.py b/xos/api/utility/onboarding.py
new file mode 100644
index 0000000..dd66d6d
--- /dev/null
+++ b/xos/api/utility/onboarding.py
@@ -0,0 +1,97 @@
+import json
+from django.http import HttpResponse
+from rest_framework.decorators import api_view
+from rest_framework.response import Response
+from rest_framework.reverse import reverse
+from rest_framework import serializers
+from rest_framework import generics
+from rest_framework import status
+from core.models import *
+from xos.apibase import XOSListCreateAPIView, XOSRetrieveUpdateDestroyAPIView, XOSPermissionDenied
+from api.xosapi_helpers import PlusModelSerializer, XOSViewSet, ReadOnlyField
+
+class OnboardingViewSet(XOSViewSet):
+ base_name = "onboarding"
+ method_name = "onboarding"
+ method_kind = "viewset"
+
+ @classmethod
+ def get_urlpatterns(self, api_path="^"):
+ patterns = [] #super(CordSubscriberViewSet, self).get_urlpatterns(api_path=api_path)
+
+ patterns.append( self.list_url("xos/ready/$", {"get": "get_xos_ready"}, "xos_ready") )
+
+ patterns.append( self.list_url("summary/$", {"get": "get_summary"}, "summary") )
+
+ patterns.append( self.list_url("services/$", {"get": "get_service_list"}, "service_list") )
+ patterns.append( self.list_url("services/(?P<service>[a-zA-Z0-9\-_]+)/ready/$", {"get": "get_service_ready"}, "service_ready") )
+
+
+ return patterns
+
+ def is_ready(self, obj):
+ return (obj.enacted is not None) and (obj.updated is not None) and (obj.enacted>=obj.updated) and (obj.backend_status.startswith("1"))
+
+ def get_xos_ready(self, request):
+ xos = XOS.objects.all()
+ if not xos:
+ return Response(false)
+
+ xos=xos[0]
+
+ result = (xos.enacted is not None) and (xos.updated is not None) and (xos.enacted>=xos.updated) and (xos.backend_status.startswith("1"))
+ return HttpResponse( json.dumps(result), content_type="application/javascript" )
+
+ def get_summary(self, request):
+ result = []
+
+ xos = XOS.objects.all()
+ if not xos:
+ result.append( ("XOS", false) )
+ else:
+ xos=xos[0]
+
+ result.append( ("XOS", self.is_ready(xos)) )
+
+ for sc in xos.service_controllers.all():
+ result.append( (sc.name, self.is_ready(sc)) )
+
+ result = "\n".join( ["%s: %s" % (x[0], x[1]) for x in result] )
+ if result:
+ result = result + "\n"
+
+ return HttpResponse( result, content_type="text/ascii" )
+
+ def get_service_list(self, request):
+ xos = XOS.objects.all()
+ if not xos:
+ return Response([])
+
+ xos=xos[0]
+
+ result = []
+ for sc in xos.service_controllers.all():
+ result.append(sc.name)
+
+ return HttpResponse( json.dumps(result), content_type="application/javascript")
+
+ def get_service_ready(self, request, service):
+ xos = XOS.objects.all()
+ if not xos:
+ return Response([])
+
+ xos=xos[0]
+
+ sc=xos.service_controllers.filter(name=service)
+ if not sc:
+ return HttpResponse("Not Found", status_code=404)
+
+ sc=sc[0]
+ result = self.is_ready(sc)
+
+ return HttpResponse( json.dumps(result), content_type="application/javascript")
+
+
+
+
+
diff --git a/xos/configurations/common/fixtures.yaml b/xos/configurations/common/fixtures.yaml
index e28b03c..6b3234e 100644
--- a/xos/configurations/common/fixtures.yaml
+++ b/xos/configurations/common/fixtures.yaml
@@ -8,6 +8,10 @@
topology_template:
node_templates:
+ xos:
+ type: tosca.nodes.XOS
+
+
# -----------------------------------------------------------------------------
# Network Parameter Types
# -----------------------------------------------------------------------------
diff --git a/xos/configurations/common/wait_for_onboarding_ready.sh b/xos/configurations/common/wait_for_onboarding_ready.sh
new file mode 100755
index 0000000..9606dbb
--- /dev/null
+++ b/xos/configurations/common/wait_for_onboarding_ready.sh
@@ -0,0 +1,27 @@
+#! /bin/bash
+
+display_usage() {
+ echo -e "\nUsage:\n$0 [xos-listen-port] [name] \n"
+}
+
+if [ $# -lt 2 ]
+then
+ display_usage
+ exit 1
+fi
+
+echo "Waiting for $2 to be onboarded"
+while [[ 1 ]]; do
+ STATUS=`curl 0.0.0.0:$1/api/utility/onboarding/$2/ready/ 2> /dev/null`
+ if [[ "$STATUS" == "true" ]]; then
+ echo "$2 is onboarded"
+ exit 0
+ fi
+ sleep 1
+# RUNNING_CONTAINER=`sudo docker ps|grep "xos"|awk '{print $$NF}'`
+# if [[ $RUNNING_CONTAINER == "" ]]; then
+# echo Container may have failed. check with \"make showlogs\'
+# exit 1
+# fi
+done
+
diff --git a/xos/configurations/common/wait_for_xos_file.sh b/xos/configurations/common/wait_for_xos_file.sh
new file mode 100755
index 0000000..1214dc4
--- /dev/null
+++ b/xos/configurations/common/wait_for_xos_file.sh
@@ -0,0 +1,24 @@
+#! /bin/bash
+
+display_usage() {
+ echo -e "\nUsage:\n$0 [fn] \n"
+}
+
+if [ $# -lt 1 ]
+then
+ display_usage
+ exit 1
+fi
+
+echo "Waiting for XOS to create file $1"
+
+until find $1 &> /dev/null
+do
+ sleep 1
+ RUNNING_CONTAINER=`sudo docker ps|grep "xos"|awk '{print $$NF}'`
+ if [[ $RUNNING_CONTAINER == "" ]]; then
+ echo Container may have failed. check with \"make showlogs\'
+ exit 1
+ fi
+done
+echo "XOS is ready"
diff --git a/xos/configurations/common/wait_for_xos_port.sh b/xos/configurations/common/wait_for_xos_port.sh
index 3ed5833..9c9e041 100755
--- a/xos/configurations/common/wait_for_xos_port.sh
+++ b/xos/configurations/common/wait_for_xos_port.sh
@@ -10,7 +10,7 @@
exit 1
fi
-echo "Waiting for XOS to come up"
+echo "Waiting for XOS to start listening on port $1"
until curl 0.0.0.0:$1 &> /dev/null
do
sleep 1
diff --git a/xos/configurations/cord-pod/Makefile b/xos/configurations/cord-pod/Makefile
index fb5b26a..f0b3c3c 100644
--- a/xos/configurations/cord-pod/Makefile
+++ b/xos/configurations/cord-pod/Makefile
@@ -1,24 +1,42 @@
+CONFIG_DIR:=$(shell pwd)
+DOCKER_COMPOSE_YML=./onboarding-docker-compose/docker-compose.yml
+BOOTSTRAP_YML=./docker-compose-bootstrap.yml
+DOCKER_PROJECT=cordpod
+
.PHONY: xos
-xos: up bootstrap
+xos: prereqs bootstrap onboarding podconfig
-up:
- sudo docker-compose up -d
- ../common/wait_for_xos_port.sh 80
+prereqs:
+ sudo make -f ../common/Makefile.prereqs
-bootstrap: nodes.yaml images.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 /root/setup/setup.yaml
- sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/nodes.yaml
- sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/images.yaml
+bootstrap:
+ echo "[BOOTSTRAP]"
+ sudo rm -f onboarding-docker-compose/docker-compose.yml
+ sudo docker-compose -p $(DOCKER_PROJECT) -f docker-compose-bootstrap.yml up -d
+ bash ../common/wait_for_xos_port.sh 81
+ sudo docker-compose -p $(DOCKER_PROJECT) -f $(BOOTSTRAP_YML) run -e CONFIG_DIR=$(CONFIG_DIR) xos_bootstrap_ui python /opt/xos/tosca/run.py none /opt/xos/configurations/cord-pod/xos.yaml
+
+onboarding:
+ echo "[ONBOARDING]"
+ # on-board any services here
+ bash ../common/wait_for_onboarding_ready.sh 81 xos
+ bash ../common/wait_for_xos_port.sh 80
+
+podconfig: nodes.yaml images.yaml
+ echo "[PODCONFIG]"
+ sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) run xos_ui python /opt/xos/tosca/run.py none /opt/xos/configurations/common/fixtures.yaml
+ sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) run xos_ui python /opt/xos/tosca/run.py none /opt/xos/configurations/common/mydeployment.yaml
+ sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) run xos_ui python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/setup.yaml
+ sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) run xos_ui python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/nodes.yaml
+ sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) run xos_ui python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/images.yaml
vtn: vtn-external.yaml
- sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/vtn-external.yaml
+ sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) run xos_ui python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/vtn-external.yaml
cord: vsg_custom_images
- sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/mgmt-net.yaml
- sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/cord-vtn-vsg.yaml
- sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/cord-volt-devices.yaml
+ sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) run xos_ui python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/mgmt-net.yaml
+ sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) run xos_ui python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/cord-vtn-vsg.yaml
+ sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) run xos_ui python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/cord-volt-devices.yaml
exampleservice:
sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/pod-exampleservice.yaml
@@ -42,10 +60,12 @@
export SETUPDIR=.; bash ./make-vtn-networkconfig-json.sh
stop:
- sudo MYIP=$(MYIP) docker-compose stop
+ test ! -s $(DOCKER_COMPOSE_YML) || sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) stop
+ sudo docker-compose -f $(BOOTSTRAP_YML) stop
rm:
- sudo MYIP=$(MYIP) docker-compose rm
+ test ! -s $(DOCKER_COMPOSE_YML) || sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) rm
+ sudo docker-compose -f $(BOOTSTRAP_YML) rm
showlogs:
sudo MYIP=$(MYIP) docker-compose logs
@@ -80,4 +100,4 @@
done
cd ../../../containers/xos; make devel
cd ../../../containers/synchronizer; make
-
+ cd ../../../containers/onboarding_synchronizer; make
diff --git a/xos/configurations/cord-pod/ceilometer.yaml b/xos/configurations/cord-pod/ceilometer.yaml
index d07f2e9..07b163e 100644
--- a/xos/configurations/cord-pod/ceilometer.yaml
+++ b/xos/configurations/cord-pod/ceilometer.yaml
@@ -124,6 +124,7 @@
kind: ceilometer
ceilometer_pub_sub_url: http://10.11.10.1:4455/
public_key: { get_artifact: [ SELF, pubkey, LOCAL_FILE] }
+ private_key_fn: /opt/xos/synchronizers/monitoring_channel/monitoring_channel_private_key
artifacts:
pubkey: /opt/xos/synchronizers/monitoring_channel/monitoring_channel_public_key
diff --git a/xos/configurations/cord-pod/docker-compose.yml b/xos/configurations/cord-pod/docker-compose-bootstrap.yml
similarity index 81%
rename from xos/configurations/cord-pod/docker-compose.yml
rename to xos/configurations/cord-pod/docker-compose-bootstrap.yml
index fa8660a..d481767 100644
--- a/xos/configurations/cord-pod/docker-compose.yml
+++ b/xos/configurations/cord-pod/docker-compose-bootstrap.yml
@@ -3,6 +3,24 @@
expose:
- "5432"
+xos_synchronizer_onboarding:
+ image: xosproject/xos-synchronizer-onboarding
+ command: bash -c "cd /opt/xos/synchronizers/onboarding; ./run.sh"
+ #command: sleep 86400
+ labels:
+ org.xosproject.kind: synchronizer
+ org.xosproject.target: onboarding
+ links:
+ - xos_db
+ volumes:
+ - /var/run/docker.sock:/var/run/docker.sock
+ - ./key_import:/opt/xos/key_import:ro
+ - ./onboarding-docker-compose:/opt/xos/synchronizers/onboarding/docker-compose
+ log_driver: "json-file"
+ log_opt:
+ max-size: "100k"
+ max-file: "5"
+
xos_synchronizer_openstack:
command: bash -c "sleep 120; python /opt/xos/synchronizers/openstack/xos-synchronizer.py"
image: xosproject/xos-synchronizer-openstack
@@ -101,21 +119,21 @@
max-size: "100k"
max-file: "5"
-xos:
- command: python /opt/xos/manage.py runserver 0.0.0.0:80 --insecure --makemigrations
+xos_bootstrap_ui:
+ command: python /opt/xos/manage.py runserver 0.0.0.0:81 --insecure --makemigrations
image: xosproject/xos
links:
- xos_db
ports:
- - "80:80"
+ - "81:81"
volumes:
- - .:/root/setup:ro
+# - .:/root/setup:ro
- ../common/xos_common_config:/opt/xos/xos_configuration/xos_common_config:ro
- ./xos_cord_config:/opt/xos/xos_configuration/xos_cord_config:ro
- ../vtn/files/xos_vtn_config:/opt/xos/xos_configuration/xos_vtn_config:ro
- - ./id_rsa.pub:/opt/xos/synchronizers/onos/onos_key.pub:ro
- - ./id_rsa.pub:/opt/xos/synchronizers/vcpe/vcpe_public_key:ro
- - ./id_rsa.pub:/opt/xos/synchronizers/monitoring_channel/monitoring_channel_public_key:ro
+# - ./id_rsa.pub:/opt/xos/synchronizers/onos/onos_key.pub:ro
+# - ./id_rsa.pub:/opt/xos/synchronizers/vcpe/vcpe_public_key:ro
+# - ./id_rsa.pub:/opt/xos/synchronizers/monitoring_channel/monitoring_channel_public_key:ro
log_driver: "json-file"
log_opt:
max-size: "100k"
diff --git a/xos/configurations/cord-pod/pod-exampleservice.yaml b/xos/configurations/cord-pod/pod-exampleservice.yaml
index 677e889..0182a59 100644
--- a/xos/configurations/cord-pod/pod-exampleservice.yaml
+++ b/xos/configurations/cord-pod/pod-exampleservice.yaml
@@ -79,10 +79,10 @@
view_url: /admin/exampleservice/exampleservice/$id$/
kind: exampleservice
public_key: { get_artifact: [ SELF, pubkey, LOCAL_FILE] }
- private_key_fn: /opt/xos/synchronizers/exampleservice/exampleservice_private_key
+ private_key_fn: /opt/xos/services/exampleservice/keys/exampleservice_rsa
service_message: hello
artifacts:
- pubkey: /opt/xos/synchronizers/exampleservice/exampleservice_public_key
+ pubkey: /opt/xos/services/exampleservice/keys/exampleservice_rsa.pub
tenant#exampletenant1:
type: tosca.nodes.ExampleTenant
diff --git a/xos/configurations/cord-pod/xos.yaml b/xos/configurations/cord-pod/xos.yaml
new file mode 100644
index 0000000..06b5eb5
--- /dev/null
+++ b/xos/configurations/cord-pod/xos.yaml
@@ -0,0 +1,85 @@
+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
+ properties:
+ ui_port: 80
+ bootstrap_ui_port: 81
+ docker_project_name: cordpod
+
+ /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: true
+ requirements:
+ - xos:
+ node: xos
+ relationship: tosca.relationships.UsedByXOS
+
+ /opt/xos/xos_configuration/xos_cord_config:
+ type: tosca.nodes.XOSVolume
+ properties:
+ host_path: { path_join: [ SELF, CONFIG_DIR, xos_cord_config, ENV_VAR ] }
+ read_only: true
+ 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
+
+ /root/setup:
+ type: tosca.nodes.XOSVolume
+ properties:
+ host_path: { path_join: [ SELF, CONFIG_DIR, ., ENV_VAR ] }
+ read_only: true
+ requirements:
+ - xos:
+ node: xos
+ relationship: tosca.relationships.UsedByXOS
+
+ /opt/xos/synchronizers/onos/onos_key.pub:
+ type: tosca.nodes.XOSVolume
+ properties:
+ host_path: { path_join: [ SELF, CONFIG_DIR, id_rsa.pub, ENV_VAR ] }
+ read_only: true
+ requirements:
+ - xos:
+ node: xos
+ relationship: tosca.relationships.UsedByXOS
+
+ /opt/xos/synchronizers/vcpe/vcpe_public_key:
+ type: tosca.nodes.XOSVolume
+ properties:
+ host_path: { path_join: [ SELF, CONFIG_DIR, id_rsa.pub, ENV_VAR ] }
+ read_only: true
+ requirements:
+ - xos:
+ node: xos
+ relationship: tosca.relationships.UsedByXOS
+
+ /opt/xos/synchronizers/monitoring_channel/monitoring_channel_public_key:
+ type: tosca.nodes.XOSVolume
+ properties:
+ host_path: { path_join: [ SELF, CONFIG_DIR, id_rsa.pub, ENV_VAR ] }
+ read_only: true
+ requirements:
+ - xos:
+ node: xos
+ relationship: tosca.relationships.UsedByXOS
diff --git a/xos/configurations/frontend/Makefile b/xos/configurations/frontend/Makefile
index 9b1ec86..46f39bf 100644
--- a/xos/configurations/frontend/Makefile
+++ b/xos/configurations/frontend/Makefile
@@ -1,24 +1,41 @@
MYIP:=$(shell hostname -i)
+CONFIG_DIR:=$(shell pwd)
+DOCKER_COMPOSE_YML=./onboarding-docker-compose/docker-compose.yml
+BOOTSTRAP_YML=./docker-compose-bootstrap.yml
+DOCKER_PROJECT=frontend
-frontend:
+frontend: prereqs bootstrap
+ bash ../common/wait_for_xos_port.sh 9999
+ sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) run xos_ui python /opt/xos/tosca/run.py none /opt/xos/configurations/common/fixtures.yaml
+ sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) run xos_ui python /opt/xos/tosca/run.py none /opt/xos/configurations/common/mydeployment.yaml
+ sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) run xos_ui python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/frontend/sample.yaml
+
+prereqs:
sudo make -f ../common/Makefile.prereqs
- sudo docker-compose up -d
- bash ../common/wait_for_xos.sh
- 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
+
+bootstrap:
+ sudo rm -f onboarding-docker-compose/docker-compose.yml
+ sudo rm -f docker-compose.yml
+ sudo docker-compose -p $(DOCKER_PROJECT) -f docker-compose-bootstrap.yml up -d
+ bash ../common/wait_for_xos_port.sh 9998
+ sudo docker-compose -p $(DOCKER_PROJECT) -f $(BOOTSTRAP_YML) run -e CONFIG_DIR=$(CONFIG_DIR) xos_bootstrap_ui python /opt/xos/tosca/run.py none /opt/xos/configurations/frontend/xos.yaml
containers:
cd ../../../containers/xos; make devel
+ cd ../../../containers/synchronizer; make
+ cd ../../../containers/onboarding_synchronizer; make
+ #cd ../../../containers/xos; make devel
stop:
- sudo docker-compose stop
+ test ! -s $(DOCKER_COMPOSE_YML) || sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) stop
+ sudo docker-compose -f $(BOOTSTRAP_YML) stop
showlogs:
sudo docker-compose logs
rm: stop
- sudo docker-compose rm
+ test ! -s $(DOCKER_COMPOSE_YML) || sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) rm
+ sudo docker-compose -p $(DOCKER_PROJECT) -f $(BOOTSTRAP_YML) rm
ps:
sudo docker-compose ps
@@ -50,3 +67,11 @@
sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/frontend/mocks/mcord.yaml
sudo docker exec frontend_xos_1 cp /opt/xos/configurations/mcord/xos_mcord_config /opt/xos/xos_configuration/
sudo docker exec frontend_xos_1 touch /opt/xos/xos/settings.py
+
+exampleservice:
+ mkdir -p key_import
+ # fake keys are fine
+ sudo bash -c "echo somekey > key_import/exampleservice_rsa"
+ sudo bash -c "echo somekey > key_import/exampleservice_rsa.pub"
+ sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) run xos_ui python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/onboard/exampleservice/exampleservice-onboard.yaml
+ bash ../common/wait_for_onboarding_ready.sh 9998 xos
diff --git a/xos/configurations/frontend/docker-compose-bootstrap.yml b/xos/configurations/frontend/docker-compose-bootstrap.yml
new file mode 100644
index 0000000..756399c
--- /dev/null
+++ b/xos/configurations/frontend/docker-compose-bootstrap.yml
@@ -0,0 +1,34 @@
+xos_db:
+ image: xosproject/xos-postgres
+ expose:
+ - "5432"
+
+xos_bootstrap_ui:
+ image: xosproject/xos
+ command: python /opt/xos/manage.py runserver 0.0.0.0:9998 --insecure --makemigrations
+ ports:
+ - "9998:9998"
+ links:
+ - xos_db
+ volumes:
+ - ../common/xos_common_config:/opt/xos/xos_configuration/xos_common_config
+ - ../vtn/files/xos_vtn_config:/opt/xos/xos_configuration/xos_vtn_config:ro
+
+xos_synchronizer_onboarding:
+ image: xosproject/xos-synchronizer-onboarding
+ #command: bash -c "sleep 120; python /opt/xos/synchronizers/onboarding/onboarding-synchronizer.py -C /root/setup/files/onboarding_synchronizer_config"
+ command: sleep 86400
+ labels:
+ org.xosproject.kind: synchronizer
+ org.xosproject.target: onboarding
+ links:
+ - xos_db
+ volumes:
+# - .:/root/setup:ro
+ - /var/run/docker.sock:/var/run/docker.sock
+ - ./key_import:/opt/xos/key_import:ro
+ - ./onboarding-docker-compose:/opt/xos/synchronizers/onboarding/docker-compose
+ log_driver: "json-file"
+ log_opt:
+ max-size: "100k"
+ max-file: "5"
diff --git a/xos/configurations/frontend/docker-compose.yml b/xos/configurations/frontend/docker-compose.yml
deleted file mode 100644
index 835eb83..0000000
--- a/xos/configurations/frontend/docker-compose.yml
+++ /dev/null
@@ -1,34 +0,0 @@
-xos_db:
- image: xosproject/xos-postgres
- expose:
- - "5432"
-
-# FUTURE
-#xos_swarm_synchronizer:
-# image: xosproject/xos-swarm-synchronizer
-# labels:
-# org.xosproject.kind: synchronizer
-# org.xosproject.target: swarm
-
-xos:
- image: xosproject/xos
- command: python /opt/xos/manage.py runserver 0.0.0.0:8000 --insecure --makemigrations
- #command: sleep 86400 # For interactive session
- ports:
- - "9999:8000"
- links:
- - xos_db
- volumes:
- - ../common/xos_common_config:/opt/xos/xos_configuration/xos_common_config
- - ../../tosca:/opt/xos/tosca
- - ../../core/xoslib:/opt/xos/core/xoslib
- - ../../core/static:/opt/xos/core/static
- - ../../core/dashboard:/opt/xos/core/dashboard
- - ../../core/templatetags:/opt/xos/core/templatetags
- - ../../core/views:/opt/xos/core/views
- - ../../templates:/opt/xos/templates
- - ../../configurations:/opt/xos/configurations
- - ../../xos:/opt/xos/xos
- - ../../api:/opt/xos/api
- - ../../services:/opt/xos/services
-
diff --git a/xos/configurations/frontend/xos.yaml b/xos/configurations/frontend/xos.yaml
new file mode 100644
index 0000000..8b286cd
--- /dev/null
+++ b/xos/configurations/frontend/xos.yaml
@@ -0,0 +1,35 @@
+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
+ properties:
+ ui_port: 9999
+ bootstrap_ui_port: 9998
+ docker_project_name: frontend
+
+ /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/admin.py b/xos/core/admin.py
index 200bb5c..c5e36be 100644
--- a/xos/core/admin.py
+++ b/xos/core/admin.py
@@ -1034,7 +1034,7 @@
list_display = ("backend_status_icon", "name", "kind",
"versionNumber", "enabled", "published")
list_display_links = ('backend_status_icon', 'name', )
- fieldList = ["backend_status_text", "name", "kind", "description", "versionNumber", "enabled", "published",
+ fieldList = ["backend_status_text", "name", "kind", "description", "controller", "versionNumber", "enabled", "published",
"view_url", "icon_url", "public_key", "private_key_fn", "service_specific_attribute", "service_specific_id"]
fieldsets = [
(None, {'fields': fieldList, 'classes': ['suit-tab suit-tab-general']})]
@@ -1051,6 +1051,27 @@
('serviceprivileges', 'Privileges')
)
+class ServiceControllerResourceInline(XOSTabularInline):
+ model = ServiceControllerResource
+ fields = ['name', 'kind', 'format', 'url']
+ extra = 0
+ suit_classes = 'suit-tab suit-tab-resources'
+
+class ServiceControllerAdmin(XOSBaseAdmin):
+ list_display = ("backend_status_icon", "name",)
+ list_display_links = ('backend_status_icon', 'name',)
+ fieldList = ["backend_status_text", "name", "xos", "base_url"]
+ fieldsets = [
+ (None, {'fields': fieldList, 'classes': ['suit-tab suit-tab-general']})]
+ inlines = [ServiceControllerResourceInline]
+ readonly_fields = ('backend_status_text', )
+
+ user_readonly_fields = fieldList
+
+ suit_form_tabs = (('general', 'Service Details'),
+ ('resources', 'Resources'),
+ )
+
class SiteNodeInline(XOSTabularInline):
model = Node
@@ -2416,6 +2437,7 @@
admin.site.register(Site, SiteAdmin)
admin.site.register(Slice, SliceAdmin)
admin.site.register(Service, ServiceAdmin)
+admin.site.register(ServiceController, ServiceControllerAdmin)
#admin.site.register(Reservation, ReservationAdmin)
admin.site.register(Network, NetworkAdmin)
admin.site.register(Port, PortAdmin)
diff --git a/xos/core/models/__init__.py b/xos/core/models/__init__.py
index 5b0ad4b..41e6b3b 100644
--- a/xos/core/models/__init__.py
+++ b/xos/core/models/__init__.py
@@ -1,8 +1,10 @@
from .plcorebase import PlCoreBase,PlCoreBaseManager,PlCoreBaseDeletionManager,PlModelMixIn
from .project import Project
from .singletonmodel import SingletonModel
+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
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 5196336..c871c7e 100644
--- a/xos/core/models/service.py
+++ b/xos/core/models/service.py
@@ -1,13 +1,22 @@
import json
from operator import attrgetter
-from core.models import PlCoreBase, PlCoreBaseManager, SingletonModel
+from core.models import PlCoreBase, PlCoreBaseManager, SingletonModel, XOS
from core.models.plcorebase import StrippedCharField
from django.db import models
from xos.exceptions import *
+import urlparse
COARSE_KIND = "coarse"
+def get_xos():
+ xos = XOS.objects.all()
+
+ if xos:
+ return xos[0]
+ else:
+ return None
+
class AttributeMixin(object):
# helper for extracting things from a json-encoded
@@ -56,6 +65,55 @@
None,
attrname))
+class ServiceController(PlCoreBase):
+ xos = models.ForeignKey(XOS, related_name='service_controllers', help_text="Pointer to XOS", default=get_xos)
+ name = StrippedCharField(max_length=30, help_text="Service Name")
+ base_url = StrippedCharField(max_length=1024, help_text="Base URL, allows use of relative URLs for resources", null=True, blank=True)
+
+ def __unicode__(self): return u'%s' % (self.name)
+
+ def save(self, *args, **kwargs):
+ super(ServiceController, self).save(*args, **kwargs)
+
+ if self.xos:
+ # force XOS to rebuild
+ # XXX somewhat hackish XXX
+ self.xos.save(update_fields=["updated"])
+
+class ServiceControllerResource(PlCoreBase):
+ KIND_CHOICES = (('models', 'Models'),
+ ('admin', 'Admin'),
+ ('django_library', 'Django Library'),
+ ('synchronizer', 'Synchronizer'),
+ ('rest_service', 'REST API (service)'),
+ ('rest_tenant', 'REST API (tenant)'),
+ ('tosca_custom_types', 'Tosca Custom Types'),
+ ('tosca_resource', 'Tosca Resource'),
+ ('private_key', 'Private Key'),
+ ('public_key', 'Public Key'))
+
+ FORMAT_CHOICES = (('python', 'Python'),
+ ('manifest', 'Manifest'),
+ ('docker', 'Docker Container'),
+ ('yaml', 'YAML'),
+ ('raw', 'raw'))
+
+ service_controller = models.ForeignKey(ServiceController, related_name='service_controller_resources',
+ help_text="The Service Controller this resource is associated with")
+
+ name = StrippedCharField(max_length=30, help_text="Object Name")
+ kind = StrippedCharField(choices=KIND_CHOICES, max_length=30)
+ format = StrippedCharField(choices=FORMAT_CHOICES, max_length=30)
+ url = StrippedCharField(max_length=1024, help_text="URL of resource", null=True, blank=True)
+
+ def __unicode__(self): return u'%s' % (self.name)
+
+ @property
+ def full_url(self):
+ if self.service_controller and self.service_controller.base_url:
+ return urlparse.urljoin(self.service_controller.base_url, self.url)
+ else:
+ return self.url
class Service(PlCoreBase, AttributeMixin):
# when subclassing a service, redefine KIND to describe the new service
@@ -81,6 +139,10 @@
max_length=30, blank=True, null=True)
service_specific_attribute = models.TextField(blank=True, null=True)
+ controller = models.ForeignKey(ServiceController, related_name='services',
+ help_text="The Service Controller this Service uses",
+ null=True, blank=True)
+
def __init__(self, *args, **kwargs):
# for subclasses, set the default kind appropriately
self._meta.get_field("kind").default = self.KIND
diff --git a/xos/core/models/xosmodel.py b/xos/core/models/xosmodel.py
new file mode 100644
index 0000000..4942241
--- /dev/null
+++ b/xos/core/models/xosmodel.py
@@ -0,0 +1,44 @@
+import os
+from django.db import models
+from core.models import PlCoreBase
+from core.models.plcorebase import StrippedCharField
+
+# 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)
+ bootstrap_ui_port = models.IntegerField(help_text="Port for XOS UI", default=81)
+ db_container_name = StrippedCharField(max_length=200, help_text="name of XOS db container", default="xos_db")
+ docker_project_name = StrippedCharField(max_length=200, help_text="docker project name")
+ enable_build = models.BooleanField(help_text="True if Onboarding Synchronizer should build XOS as necessary", default=True)
+
+ def __unicode__(self): return u'%s' % (self.name)
+
+ def __init__(self, *args, **kwargs):
+ super(XOS, self).__init__(*args, **kwargs)
+
+ def save(self, *args, **kwds):
+ super(XOS, self).save(*args, **kwds)
+
+# def can_update(self, user):
+# return user.can_update_site(self.site, allow=['tech'])
+
+ def rebuild(self):
+ for service_controller in self.service_controllers.all():
+ for scr in service_controller.service_controller_resources.all():
+ scr.save()
+ 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/onboard/README.md b/xos/onboard/README.md
new file mode 100644
index 0000000..2030708
--- /dev/null
+++ b/xos/onboard/README.md
@@ -0,0 +1,3 @@
+This directory is a temporary placeholder for services that can be on-boarded.
+
+Once we move to Gerritt and service-per-repo, this directory will be removed.
diff --git a/xos/services/exampleservice/admin.py b/xos/onboard/exampleservice/admin.py
similarity index 100%
rename from xos/services/exampleservice/admin.py
rename to xos/onboard/exampleservice/admin.py
diff --git a/xos/api/service/exampleservice.py b/xos/onboard/exampleservice/api/service/exampleservice.py
similarity index 100%
rename from xos/api/service/exampleservice.py
rename to xos/onboard/exampleservice/api/service/exampleservice.py
diff --git a/xos/api/tenant/exampletenant.py b/xos/onboard/exampleservice/api/tenant/exampletenant.py
similarity index 100%
rename from xos/api/tenant/exampletenant.py
rename to xos/onboard/exampleservice/api/tenant/exampletenant.py
diff --git a/xos/onboard/exampleservice/exampleservice-onboard-longform.yaml b/xos/onboard/exampleservice/exampleservice-onboard-longform.yaml
new file mode 100644
index 0000000..0eddd51
--- /dev/null
+++ b/xos/onboard/exampleservice/exampleservice-onboard-longform.yaml
@@ -0,0 +1,57 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: Onboard the exampleservice
+
+imports:
+ - custom_types/xos.yaml
+
+topology_template:
+ node_templates:
+ exampleservice:
+ type: tosca.nodes.ServiceController
+ properties:
+ base_url: file:/opt/xos/onboard/exampleservice/
+
+ exampleservice_models:
+ type: tosca.nodes.ServiceControllerResource
+ properties:
+ kind: models
+ format: python
+ url: models.py
+ requirements:
+ - controller:
+ node: exampleservice
+ relationship: tosca.relationships.UsedByController
+
+ exampleservice_admin:
+ type: tosca.nodes.ServiceControllerResource
+ properties:
+ kind: admin
+ format: python
+ url: admin.py
+ requirements:
+ - controller:
+ node: exampleservice
+ relationship: tosca.relationships.UsedByController
+
+ exampleservice_synchronizer:
+ type: tosca.nodes.ServiceControllerResource
+ properties:
+ kind: synchronizer
+ format: manifest
+ url: synchronizer/manifest
+ requirements:
+ - controller:
+ node: exampleservice
+ relationship: tosca.relationships.UsedByController
+
+ exampleservice_tosca_types:
+ type: tosca.nodes.ServiceControllerResource
+ properties:
+ kind: tosca_custom_types
+ format: yaml
+ url: exampleservice.yaml
+ requirements:
+ - controller:
+ node: exampleservice
+ relationship: tosca.relationships.UsedByController
diff --git a/xos/onboard/exampleservice/exampleservice-onboard.yaml b/xos/onboard/exampleservice/exampleservice-onboard.yaml
new file mode 100644
index 0000000..91dbb2e
--- /dev/null
+++ b/xos/onboard/exampleservice/exampleservice-onboard.yaml
@@ -0,0 +1,24 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: Onboard the exampleservice
+
+imports:
+ - custom_types/xos.yaml
+
+topology_template:
+ node_templates:
+ exampleservice:
+ type: tosca.nodes.ServiceController
+ properties:
+ base_url: file:///opt/xos/onboard/exampleservice/
+ # The following will concatenate with base_url automatically, if
+ # base_url is non-null.
+ models: models.py
+ admin: admin.py
+ synchronizer: synchronizer/manifest
+ tosca_custom_types: exampleservice.yaml
+ rest_service: api/service/exampleservice.py
+ rest_tenant: api/tenant/exampletenant.py
+ private_key: file:///opt/xos/key_import/exampleservice_rsa
+ public_key: file:///opt/xos/key_import/exampleservice_rsa.pub
+
diff --git a/xos/tosca/custom_types/exampleservice.m4 b/xos/onboard/exampleservice/exampleservice.m4
similarity index 100%
rename from xos/tosca/custom_types/exampleservice.m4
rename to xos/onboard/exampleservice/exampleservice.m4
diff --git a/xos/tosca/custom_types/exampleservice.yaml b/xos/onboard/exampleservice/exampleservice.yaml
similarity index 100%
rename from xos/tosca/custom_types/exampleservice.yaml
rename to xos/onboard/exampleservice/exampleservice.yaml
diff --git a/xos/onboard/exampleservice/macros.m4 b/xos/onboard/exampleservice/macros.m4
new file mode 100644
index 0000000..1f48f10
--- /dev/null
+++ b/xos/onboard/exampleservice/macros.m4
@@ -0,0 +1,84 @@
+# Note: Tosca derived_from isn't working the way I think it should, it's not
+# inheriting from the parent template. Until we get that figured out, use
+# m4 macros do our inheritance
+
+define(xos_base_props,
+ 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)
+# Service
+define(xos_base_service_caps,
+ scalable:
+ type: tosca.capabilities.Scalable
+ service:
+ type: tosca.capabilities.xos.Service)
+define(xos_base_service_props,
+ kind:
+ type: string
+ default: generic
+ description: Type of service.
+ view_url:
+ type: string
+ required: false
+ description: URL to follow when icon is clicked in the Service Directory.
+ icon_url:
+ type: string
+ required: false
+ description: ICON to display in the Service Directory.
+ enabled:
+ type: boolean
+ default: true
+ published:
+ type: boolean
+ default: true
+ description: If True then display this Service in the Service Directory.
+ public_key:
+ type: string
+ required: false
+ description: Public key to install into Instances to allows Services to SSH into them.
+ private_key_fn:
+ type: string
+ required: false
+ description: Location of private key file
+ versionNumber:
+ type: string
+ required: false
+ description: Version number of Service.)
+# Subscriber
+define(xos_base_subscriber_caps,
+ subscriber:
+ type: tosca.capabilities.xos.Subscriber)
+define(xos_base_subscriber_props,
+ kind:
+ type: string
+ default: generic
+ description: Kind of subscriber
+ service_specific_id:
+ type: string
+ required: false
+ description: Service specific ID opaque to XOS but meaningful to service)
+define(xos_base_tenant_props,
+ kind:
+ type: string
+ default: generic
+ description: Kind of tenant
+ service_specific_id:
+ type: string
+ required: false
+ description: Service specific ID opaque to XOS but meaningful to service)
+
+# end m4 macros
+
diff --git a/xos/onboard/exampleservice/make_synchronizer_manifest.sh b/xos/onboard/exampleservice/make_synchronizer_manifest.sh
new file mode 100644
index 0000000..4058982
--- /dev/null
+++ b/xos/onboard/exampleservice/make_synchronizer_manifest.sh
@@ -0,0 +1,2 @@
+#! /bin/bash
+find synchronizer -type f | cut -b 14- > synchronizer/manifest
diff --git a/xos/services/exampleservice/models.py b/xos/onboard/exampleservice/models.py
similarity index 100%
rename from xos/services/exampleservice/models.py
rename to xos/onboard/exampleservice/models.py
diff --git a/xos/synchronizers/exampleservice/exampleservice-synchronizer.py b/xos/onboard/exampleservice/synchronizer/exampleservice-synchronizer.py
similarity index 100%
copy from xos/synchronizers/exampleservice/exampleservice-synchronizer.py
copy to xos/onboard/exampleservice/synchronizer/exampleservice-synchronizer.py
diff --git a/xos/synchronizers/exampleservice/exampleservice_config b/xos/onboard/exampleservice/synchronizer/exampleservice_config
similarity index 100%
copy from xos/synchronizers/exampleservice/exampleservice_config
copy to xos/onboard/exampleservice/synchronizer/exampleservice_config
diff --git a/xos/onboard/exampleservice/synchronizer/manifest b/xos/onboard/exampleservice/synchronizer/manifest
new file mode 100644
index 0000000..8f43610
--- /dev/null
+++ b/xos/onboard/exampleservice/synchronizer/manifest
@@ -0,0 +1,10 @@
+manifest
+steps/sync_exampletenant.py
+steps/roles/install_apache/tasks/main.yml
+steps/roles/create_index/templates/index.html.j2
+steps/roles/create_index/tasks/main.yml
+steps/exampletenant_playbook.yaml
+exampleservice-synchronizer.py
+model-deps
+run.sh
+exampleservice_config
diff --git a/xos/synchronizers/exampleservice/model-deps b/xos/onboard/exampleservice/synchronizer/model-deps
similarity index 100%
copy from xos/synchronizers/exampleservice/model-deps
copy to xos/onboard/exampleservice/synchronizer/model-deps
diff --git a/xos/onboard/exampleservice/synchronizer/run.sh b/xos/onboard/exampleservice/synchronizer/run.sh
new file mode 100755
index 0000000..e6da8f6
--- /dev/null
+++ b/xos/onboard/exampleservice/synchronizer/run.sh
@@ -0,0 +1,2 @@
+export XOS_DIR=/opt/xos
+python exampleservice-synchronizer.py -C $XOS_DIR/synchronizers/exampleservice/exampleservice_config
diff --git a/xos/synchronizers/exampleservice/steps/exampletenant_playbook.yaml b/xos/onboard/exampleservice/synchronizer/steps/exampletenant_playbook.yaml
similarity index 100%
copy from xos/synchronizers/exampleservice/steps/exampletenant_playbook.yaml
copy to xos/onboard/exampleservice/synchronizer/steps/exampletenant_playbook.yaml
diff --git a/xos/synchronizers/exampleservice/steps/roles/create_index/tasks/main.yml b/xos/onboard/exampleservice/synchronizer/steps/roles/create_index/tasks/main.yml
similarity index 100%
copy from xos/synchronizers/exampleservice/steps/roles/create_index/tasks/main.yml
copy to xos/onboard/exampleservice/synchronizer/steps/roles/create_index/tasks/main.yml
diff --git a/xos/synchronizers/exampleservice/steps/roles/create_index/templates/index.html.j2 b/xos/onboard/exampleservice/synchronizer/steps/roles/create_index/templates/index.html.j2
similarity index 100%
copy from xos/synchronizers/exampleservice/steps/roles/create_index/templates/index.html.j2
copy to xos/onboard/exampleservice/synchronizer/steps/roles/create_index/templates/index.html.j2
diff --git a/xos/synchronizers/exampleservice/steps/roles/install_apache/tasks/main.yml b/xos/onboard/exampleservice/synchronizer/steps/roles/install_apache/tasks/main.yml
similarity index 100%
copy from xos/synchronizers/exampleservice/steps/roles/install_apache/tasks/main.yml
copy to xos/onboard/exampleservice/synchronizer/steps/roles/install_apache/tasks/main.yml
diff --git a/xos/synchronizers/exampleservice/steps/sync_exampletenant.py b/xos/onboard/exampleservice/synchronizer/steps/sync_exampletenant.py
similarity index 100%
copy from xos/synchronizers/exampleservice/steps/sync_exampletenant.py
copy to xos/onboard/exampleservice/synchronizer/steps/sync_exampletenant.py
diff --git a/xos/services/exampleservice/README.md b/xos/services/exampleservice/README.md
deleted file mode 100644
index ce6210d..0000000
--- a/xos/services/exampleservice/README.md
+++ /dev/null
@@ -1,8 +0,0 @@
-# ExampleService
-
-This is an example XOS service, specifically the Django Model and Admin.
-
-The Synchronizer corresponding to this service can be found in `../../synchronizers/exampleservice`.
-
-Documentation for this is located here: [XOS Guide : DevGuide : ExampleService](http://guide.xosproject.org/devguide/exampleservice/).
-
diff --git a/xos/services/exampleservice/__init__.py b/xos/services/exampleservice/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/xos/services/exampleservice/__init__.py
+++ /dev/null
diff --git a/xos/synchronizers/base/SyncInstanceUsingAnsible.py b/xos/synchronizers/base/SyncInstanceUsingAnsible.py
index fef8f86..49ca23b 100644
--- a/xos/synchronizers/base/SyncInstanceUsingAnsible.py
+++ b/xos/synchronizers/base/SyncInstanceUsingAnsible.py
@@ -21,7 +21,6 @@
# observes=VSGTenant
# requested_interval=0
# template_name = "sync_vcpetenant.yaml"
- # service_key_name = "/opt/xos/observers/vcpe/vcpe_private_key"
def __init__(self, **args):
SyncStep.__init__(self, **args)
@@ -96,7 +95,10 @@
"username": "ubuntu",
"ssh_ip": instance.get_ssh_ip(),
}
- key_name = self.service_key_name
+ if (instance.slice) and (instance.slice.service) and (instance.slice.service.private_key_fn):
+ key_name = instance.slice.service.private_key_fn
+ else:
+ raise Exception("Make sure to set private_key_fn in the service")
elif (instance.isolation == "container"):
# container on bare metal
node = self.get_node(instance)
diff --git a/xos/synchronizers/base/event_loop.py b/xos/synchronizers/base/event_loop.py
index 4d57deb..ae97329 100644
--- a/xos/synchronizers/base/event_loop.py
+++ b/xos/synchronizers/base/event_loop.py
@@ -9,6 +9,7 @@
import json
import pdb
import pprint
+import traceback
from datetime import datetime
@@ -349,9 +350,11 @@
if (step_status[d] is STEP_STATUS_WORKING):
logger.info(" step %s wait on dep %s" % (step.__name__, d))
cond.wait()
+ logger.info(" step %s wait on dep %s cond returned" % (step.__name__, d))
elif step_status[d] == STEP_STATUS_OK:
go = True
else:
+ logger.info(" step %s has failed dep %s" % (step.__name__, d))
go = False
failed_dep = d
cond.release()
@@ -361,6 +364,7 @@
go = True
if (not go):
+ logger.info("Step %s skipped" % step.__name__)
self.consolePrint(bcolors.FAIL + "Step %r skipped on %r" % (step,failed_dep) + bcolors.ENDC)
# SMBAKER: sync_step was not defined here, so I changed
# this from 'sync_step' to 'step'. Verify.
@@ -416,7 +420,7 @@
if failed_objects:
self.failed_step_objects.update(failed_objects)
- logger.info("Step %r succeeded" % sync_step.__name__)
+ logger.info("Step %r succeeded, deletion=%s" % (sync_step.__name__, deletion))
self.consolePrint(bcolors.OKGREEN + "Step %r succeeded" % sync_step.__name__ + bcolors.ENDC)
my_status = STEP_STATUS_OK
self.update_run_time(sync_step,deletion)
@@ -462,8 +466,27 @@
self.run_once()
+ def check_db_connection_okay(self):
+ # django implodes if the database connection is closed by docker-compose
+ try:
+ diag = Diag.objects.filter(name="foo").first()
+ except Exception, e:
+ from django import db
+ if "connection already closed" in traceback.format_exc():
+ logger.error("XXX connection already closed")
+ try:
+# if db.connection:
+# db.connection.close()
+ db.close_connection()
+ except:
+ logger.log_exc("XXX we failed to fix the failure")
+ else:
+ logger.log_exc("XXX some other error")
+
def run_once(self):
try:
+ self.check_db_connection_okay()
+
loop_start = time.time()
error_map_file = getattr(Config(), "error_map_path", XOS_DIR + "/error_map.txt")
self.error_mapper = ErrorMapper(error_map_file)
diff --git a/xos/synchronizers/base/syncstep.py b/xos/synchronizers/base/syncstep.py
index 2fa6c38..eeb61db 100644
--- a/xos/synchronizers/base/syncstep.py
+++ b/xos/synchronizers/base/syncstep.py
@@ -141,6 +141,8 @@
def sync_record(self, o):
+ logger.info("Sync_record called for %s %s" % (o.__class__.__name__, str(o)))
+
try:
controller = o.get_controller()
controller_register = json.loads(controller.backend_register)
diff --git a/xos/synchronizers/exampleservice/exampleservice-synchronizer.py b/xos/synchronizers/exampleservice_old/exampleservice-synchronizer.py
similarity index 100%
rename from xos/synchronizers/exampleservice/exampleservice-synchronizer.py
rename to xos/synchronizers/exampleservice_old/exampleservice-synchronizer.py
diff --git a/xos/synchronizers/exampleservice/exampleservice_config b/xos/synchronizers/exampleservice_old/exampleservice_config
similarity index 100%
rename from xos/synchronizers/exampleservice/exampleservice_config
rename to xos/synchronizers/exampleservice_old/exampleservice_config
diff --git a/xos/synchronizers/exampleservice/model-deps b/xos/synchronizers/exampleservice_old/model-deps
similarity index 100%
rename from xos/synchronizers/exampleservice/model-deps
rename to xos/synchronizers/exampleservice_old/model-deps
diff --git a/xos/synchronizers/exampleservice/steps/exampletenant_playbook.yaml b/xos/synchronizers/exampleservice_old/steps/exampletenant_playbook.yaml
similarity index 100%
rename from xos/synchronizers/exampleservice/steps/exampletenant_playbook.yaml
rename to xos/synchronizers/exampleservice_old/steps/exampletenant_playbook.yaml
diff --git a/xos/synchronizers/exampleservice/steps/roles/create_index/tasks/main.yml b/xos/synchronizers/exampleservice_old/steps/roles/create_index/tasks/main.yml
similarity index 100%
rename from xos/synchronizers/exampleservice/steps/roles/create_index/tasks/main.yml
rename to xos/synchronizers/exampleservice_old/steps/roles/create_index/tasks/main.yml
diff --git a/xos/synchronizers/exampleservice/steps/roles/create_index/templates/index.html.j2 b/xos/synchronizers/exampleservice_old/steps/roles/create_index/templates/index.html.j2
similarity index 100%
rename from xos/synchronizers/exampleservice/steps/roles/create_index/templates/index.html.j2
rename to xos/synchronizers/exampleservice_old/steps/roles/create_index/templates/index.html.j2
diff --git a/xos/synchronizers/exampleservice/steps/roles/install_apache/tasks/main.yml b/xos/synchronizers/exampleservice_old/steps/roles/install_apache/tasks/main.yml
similarity index 100%
rename from xos/synchronizers/exampleservice/steps/roles/install_apache/tasks/main.yml
rename to xos/synchronizers/exampleservice_old/steps/roles/install_apache/tasks/main.yml
diff --git a/xos/synchronizers/exampleservice/steps/sync_exampletenant.py b/xos/synchronizers/exampleservice_old/steps/sync_exampletenant.py
similarity index 100%
rename from xos/synchronizers/exampleservice/steps/sync_exampletenant.py
rename to xos/synchronizers/exampleservice_old/steps/sync_exampletenant.py
diff --git a/xos/synchronizers/model_policy.py b/xos/synchronizers/model_policy.py
index ef31d41..aa12092 100644
--- a/xos/synchronizers/model_policy.py
+++ b/xos/synchronizers/model_policy.py
@@ -3,10 +3,11 @@
import pdb
from generate.dependency_walker import *
from synchronizers.openstack import model_policies
-from xos.logger import logger
+from xos.logger import Logger, logging
from datetime import datetime
from django.utils import timezone
import time
+import traceback
from core.models import *
from django.db import reset_queries
from django.db.transaction import atomic
@@ -15,6 +16,8 @@
modelPolicyEnabled = True
bad_instances=[]
+logger = Logger(level=logging.INFO)
+
def EnableModelPolicy(x):
global modelPolicyEnabled
modelPolicyEnabled = x
@@ -40,9 +43,10 @@
if (save_fields):
d.save(update_fields=save_fields)
except AttributeError,e:
+ logger.log_exc("AttributeError in update_dep")
raise e
except Exception,e:
- logger.info('Could not save %r. Exception: %r'%(d,e), extra=d.tologdict())
+ logger.log_exc("Exception in update_dep")
def delete_if_inactive(d, o):
try:
@@ -75,7 +79,7 @@
try:
policy_handler = getattr(model_policies, policy_name, None)
- logger.error("POLICY HANDLER: %s %s" % (policy_name, policy_handler))
+ logger.info("MODEL POLICY: handler %s %s" % (policy_name, policy_handler))
if policy_handler is not None:
if (deleted):
try:
@@ -84,23 +88,45 @@
pass
else:
policy_handler.handle(instance)
+ logger.info("MODEL POLICY: completed handler %s %s" % (policy_name, policy_handler))
except:
- logger.log_exc("Model Policy Error:")
+ logger.log_exc("MODEL POLICY: Exception when running handler")
try:
instance.policed=timezone.now()
instance.save(update_fields=['policed'])
except:
- logging.error('Object %r is defective'%instance)
+ logger.log_exc('MODEL POLICY: Object %r is defective'%instance)
bad_instances.append(instance)
def noop(o,p):
pass
+def check_db_connection_okay():
+ # django implodes if the database connection is closed by docker-compose
+ from django import db
+ try:
+ db.connection.cursor()
+ #diag = Diag.objects.filter(name="foo").first()
+ except Exception, e:
+ if "connection already closed" in traceback.format_exc():
+ logger.error("XXX connection already closed")
+ try:
+# if db.connection:
+# db.connection.close()
+ db.close_connection()
+ except:
+ logger.log_exc("XXX we failed to fix the failure")
+ else:
+ logger.log_exc("XXX some other error")
+
def run_policy():
while (True):
start = time.time()
- run_policy_once()
+ try:
+ run_policy_once()
+ except:
+ logger.log_exc("MODEL_POLICY: Exception in run_policy()")
if (time.time()-start<1):
time.sleep(1)
@@ -110,6 +136,10 @@
objects = []
deleted_objects = []
+ logger.info("MODEL POLICY: run_policy_once()")
+
+ check_db_connection_okay()
+
for m in models:
res = m.objects.filter((Q(policed__lt=F('updated')) | Q(policed=None)) & Q(no_policy=False))
objects.extend(res)
@@ -137,4 +167,6 @@
reset_queries()
except:
# this shouldn't happen, but in case it does, catch it...
- logger.log_exc("exception in reset_queries")
+ logger.log_exc("MODEL POLICY: exception in reset_queries")
+
+ logger.info("MODEL POLICY: finished run_policy_once()")
diff --git a/xos/synchronizers/onboarding/files/__init__.py b/xos/synchronizers/onboarding/files/__init__.py
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/xos/synchronizers/onboarding/files/__init__.py
@@ -0,0 +1 @@
+
diff --git a/xos/synchronizers/onboarding/model-deps b/xos/synchronizers/onboarding/model-deps
new file mode 100644
index 0000000..4aa86c7
--- /dev/null
+++ b/xos/synchronizers/onboarding/model-deps
@@ -0,0 +1,8 @@
+{
+ "XOS": [
+ "ServiceController"
+ ],
+ "ServiceController": [
+ "ServiceControllerResource"
+ ]
+}
diff --git a/xos/synchronizers/onboarding/onboarding-synchronizer.py b/xos/synchronizers/onboarding/onboarding-synchronizer.py
new file mode 100755
index 0000000..84bec4f
--- /dev/null
+++ b/xos/synchronizers/onboarding/onboarding-synchronizer.py
@@ -0,0 +1,11 @@
+#!/usr/bin/env python
+
+# This imports and runs ../../xos-observer.py
+
+import importlib
+import os
+import sys
+observer_path = os.path.join(os.path.dirname(os.path.realpath(__file__)),"../../synchronizers/base")
+sys.path.append(observer_path)
+mod = importlib.import_module("xos-synchronizer")
+mod.main()
diff --git a/xos/synchronizers/onboarding/onboarding_synchronizer_config b/xos/synchronizers/onboarding/onboarding_synchronizer_config
new file mode 100644
index 0000000..e2b92fd
--- /dev/null
+++ b/xos/synchronizers/onboarding/onboarding_synchronizer_config
@@ -0,0 +1,38 @@
+
+[plc]
+name=plc
+deployment=VICCI
+
+[db]
+name=xos
+user=postgres
+password=password
+host=localhost
+port=5432
+
+[api]
+host=128.112.171.237
+port=8000
+ssl_key=None
+ssl_cert=None
+ca_ssl_cert=None
+ratelimit_enabled=0
+omf_enabled=0
+mail_support_address=support@localhost
+nova_enabled=True
+
+[observer]
+name=onboarding
+dependency_graph=/opt/xos/synchronizers/onboarding/model-deps
+steps_dir=/opt/xos/synchronizers/onboarding/steps
+sys_dir=/opt/xos/synchronizers/onboarding/sys
+deleters_dir=/opt/xos/synchronizers/onboarding/deleters
+log_file=console
+driver=None
+backoff_disabled=True
+pretend=False
+save_ansible_output=True
+
+[feefie]
+client_id='vicci_dev_central'
+user_id='pl'
diff --git a/xos/synchronizers/onboarding/run.sh b/xos/synchronizers/onboarding/run.sh
new file mode 100755
index 0000000..d52d39c
--- /dev/null
+++ b/xos/synchronizers/onboarding/run.sh
@@ -0,0 +1,2 @@
+export XOS_DIR=/opt/xos
+python onboarding-synchronizer.py -C $XOS_DIR/synchronizers/onboarding/onboarding_synchronizer_config
diff --git a/xos/synchronizers/onboarding/steps/sync_servicecontroller.py b/xos/synchronizers/onboarding/steps/sync_servicecontroller.py
new file mode 100644
index 0000000..77d8e12
--- /dev/null
+++ b/xos/synchronizers/onboarding/steps/sync_servicecontroller.py
@@ -0,0 +1,53 @@
+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, ServiceController
+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 SyncServiceController(SyncStep, XOSBuilder):
+ provides=[ServiceController]
+ observes=ServiceController
+ requested_interval=0
+ playbook = "sync_servicecontroller.yaml"
+
+ def __init__(self, **args):
+ SyncStep.__init__(self, **args)
+ XOSBuilder.__init__(self)
+
+ def sync_record(self, sc):
+ logger.info("Sync'ing ServiceController %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])))
+
+ dockerfiles = [self.create_synchronizer_dockerfile(sc)]
+ tenant_fields = {"dockerfiles": dockerfiles,
+ "build_dir": self.build_dir,
+ "ansible_tag": sc.__class__.__name__ + "_" + str(sc.id)}
+
+ path="servicecontroller"
+ res = run_template(self.playbook, tenant_fields, path=path)
+
+ def delete_record(self, m):
+ pass
+
+ def fetch_pending(self, deleted=False):
+ pend = super(SyncServiceController, self).fetch_pending(deleted)
+ return pend
+
diff --git a/xos/synchronizers/onboarding/steps/sync_servicecontroller.yaml b/xos/synchronizers/onboarding/steps/sync_servicecontroller.yaml
new file mode 100644
index 0000000..9431427
--- /dev/null
+++ b/xos/synchronizers/onboarding/steps/sync_servicecontroller.yaml
@@ -0,0 +1,20 @@
+---
+- hosts: 127.0.0.1
+ connection: local
+
+ vars:
+ dockerfiles:
+ {% for dockerfile in dockerfiles %}
+ - docker_image_name: {{ dockerfile.docker_image_name }}
+ dockerfile_fn: {{ dockerfile.dockerfile_fn }}
+ {% endfor %}
+
+ tasks:
+ {% for dockerfile in dockerfiles %}
+ - name: build_docker_{{ dockerfile.docker_image_name }}
+ shell: chdir={{ build_dir }} docker build -f {{ dockerfile.dockerfile_fn }} --rm -t {{ dockerfile.docker_image_name }} .
+ {% endfor %}
+
+# - build_dockers:
+# shell: docker build -f {{ '{{' }} item.dockerfile_fn {{ '}}' }} --rm -t {{ '{{' }} item.docker_image_name {{ '}}' }} .
+# with items: "dockerfiles"
diff --git a/xos/synchronizers/onboarding/steps/sync_servicecontrollerresource.py b/xos/synchronizers/onboarding/steps/sync_servicecontrollerresource.py
new file mode 100644
index 0000000..59ae93f
--- /dev/null
+++ b/xos/synchronizers/onboarding/steps/sync_servicecontrollerresource.py
@@ -0,0 +1,37 @@
+import os
+import sys
+import base64
+from django.db.models import F, Q
+from xos.config import Config
+from synchronizers.base.syncstep import SyncStep
+from core.models import Service, ServiceController, ServiceControllerResource
+from xos.logger import Logger, logging
+
+# 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 SyncServiceControllerResource(SyncStep, XOSBuilder):
+ provides=[ServiceControllerResource]
+ observes=ServiceControllerResource
+ requested_interval=0
+
+ def __init__(self, **args):
+ SyncStep.__init__(self, **args)
+ XOSBuilder.__init__(self)
+
+ def sync_record(self, scr):
+ logger.info("Sync'ing ServiceControllerResource %s" % scr)
+ self.download_resource(scr)
+
+ def delete_record(self, m):
+ pass
+
+ def fetch_pending(self, deleted=False):
+ pend = super(SyncServiceControllerResource, self).fetch_pending(deleted)
+ return pend
+
diff --git a/xos/synchronizers/onboarding/steps/sync_xos.py b/xos/synchronizers/onboarding/steps/sync_xos.py
new file mode 100644
index 0000000..dec7a34
--- /dev/null
+++ b/xos/synchronizers/onboarding/steps/sync_xos.py
@@ -0,0 +1,52 @@
+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
+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 SyncXOS(SyncStep, XOSBuilder):
+ provides=[XOS]
+ observes=XOS
+ requested_interval=0
+ playbook = "sync_xos.yaml"
+
+ def __init__(self, **args):
+ SyncStep.__init__(self, **args)
+ XOSBuilder.__init__(self)
+
+ def sync_record(self, xos):
+ logger.info("Sync'ing XOS %s" % xos)
+
+ if (not xos.enable_build):
+ raise DeferredException("XOS build is currently disabled")
+
+ self.create_docker_compose()
+
+ dockerfiles = [self.create_ui_dockerfile()]
+ tenant_fields = {"dockerfiles": dockerfiles,
+ "build_dir": self.build_dir,
+ "docker_project_name": xos.docker_project_name,
+ "ansible_tag": xos.__class__.__name__ + "_" + str(xos.id)}
+
+ path="XOS"
+ res = run_template(self.playbook, tenant_fields, path=path)
+
+ def delete_record(self, m):
+ pass
+
+ def fetch_pending(self, deleted=False):
+ pend = super(SyncXOS, self).fetch_pending(deleted)
+ return pend
+
diff --git a/xos/synchronizers/onboarding/steps/sync_xos.yaml b/xos/synchronizers/onboarding/steps/sync_xos.yaml
new file mode 100644
index 0000000..8a98873
--- /dev/null
+++ b/xos/synchronizers/onboarding/steps/sync_xos.yaml
@@ -0,0 +1,20 @@
+---
+- hosts: 127.0.0.1
+ connection: local
+
+ vars:
+ dockerfiles:
+ {% for dockerfile in dockerfiles %}
+ - docker_image_name: {{ dockerfile.docker_image_name }}
+ dockerfile_fn: {{ dockerfile.dockerfile_fn }}
+ {% endfor %}
+
+ tasks:
+ {% for dockerfile in dockerfiles %}
+ - name: build_docker_{{ dockerfile.docker_image_name }}
+ shell: chdir={{ build_dir }} docker build -f {{ dockerfile.dockerfile_fn }} --rm -t {{ dockerfile.docker_image_name }} .
+ {% endfor %}
+
+ - name: run docker-compose
+ shell: docker-compose -p {{ docker_project_name }} -f /opt/xos/synchronizers/onboarding/docker-compose/docker-compose.yml up -d
+
diff --git a/xos/synchronizers/onboarding/templates/docker-compose.yml.j2 b/xos/synchronizers/onboarding/templates/docker-compose.yml.j2
new file mode 100644
index 0000000..faa9d02
--- /dev/null
+++ b/xos/synchronizers/onboarding/templates/docker-compose.yml.j2
@@ -0,0 +1,48 @@
+{% for container_name, container in containers.iteritems() %}
+
+{{ container_name}}:
+# container_name: {{ container.container_base_name }}_{{ container_name }}_1
+ image: {{ container.image }}
+{%- if container.command %}
+ command: {{ container.command }}
+{%- endif %}
+{%- if container.ports %}
+ ports:
+{%- for src,dest in container.ports.iteritems() %}
+ - "{{ src }}:{{ dest }}"
+{%- endfor %}
+{%- endif %}
+{%- if container.links %}
+ links:
+{%- for link in container.links %}
+ - {{ link }}
+{%- endfor %}
+{%- endif %}
+{%- if container.external_links %}
+ external_links:
+{%- for link in container.external_links %}
+ - {{ link }}
+{%- endfor %}
+{%- endif %}
+{%- if container.volumes %}
+ volumes:
+{%- for volume in container.volumes %}
+{%- if volume.read_only %}
+ - {{ volume.host_path }}:{{ volume.container_path }}:ro
+{%- else %}
+ - {{ volume.host_path }}:{{ volume.container_path }}
+{%- endif %}
+{%- endfor %}
+{%- endif %}
+{%- if container.expose %}
+ expose:
+{%- for expose in container.expose %}
+ - "{{ expose }}"
+{%- endfor %}
+{%- endif %}
+ log_driver: "json-file"
+ log_opt:
+ max-size: "100k"
+ max-file: "5"
+
+{%- endfor %}
diff --git a/xos/synchronizers/onboarding/xosbuilder.py b/xos/synchronizers/onboarding/xosbuilder.py
new file mode 100644
index 0000000..ffb66ee
--- /dev/null
+++ b/xos/synchronizers/onboarding/xosbuilder.py
@@ -0,0 +1,252 @@
+import os
+import base64
+import jinja2
+import string
+import sys
+import urllib2
+import urlparse
+import xmlrpclib
+
+from xos.config import Config
+from core.models import Service, ServiceController, ServiceControllerResource, XOS
+from xos.logger import Logger, logging
+
+logger = Logger(level=logging.INFO)
+
+class XOSBuilder(object):
+ UI_KINDS=["models", "admin", "django_library", "rest_service", "rest_tenant", "tosca_custom_types", "tosca_resource","public_key"]
+ SYNC_CONTROLLER_KINDS=["synchronizer", "private_key", "public_key"]
+ SYNC_ALLCONTROLLER_KINDS=["models", "django_library"]
+
+ def __init__(self):
+ self.source_ui_image = "xosproject/xos"
+ self.source_sync_image = "xosproject/xos-synchronizer-openstack"
+ self.build_dir = "/opt/xos/BUILD/"
+
+ # stuff that has to do with downloading
+
+ def get_dest_dir(self, scr):
+ xos_base = "opt/xos"
+ service_name = scr.service_controller.name
+ base_dirs = {"models": "%s/services/%s/" % (xos_base, service_name),
+ "admin": "%s/services/%s/" % (xos_base, service_name),
+ "django_library": "%s/services/%s/" % (xos_base, service_name),
+ "synchronizer": "%s/synchronizers/%s/" % (xos_base, service_name),
+ "tosca_custom_types": "%s/tosca/custom_types/" % (xos_base),
+ "tosca_resource": "%s/tosca/resources/" % (xos_base),
+ "rest_service": "%s/api/service/" % (xos_base),
+ "rest_tenant": "%s/api/tenant/" % (xos_base),
+ "private_key": "%s/services/%s/keys" % (xos_base, service_name),
+ "public_key": "%s/services/%s/keys/" % (xos_base, service_name)}
+ return base_dirs[scr.kind]
+
+ def get_build_fn(self, scr):
+ dest_dir = self.get_dest_dir(scr)
+ dest_fn = os.path.split(urlparse.urlsplit(scr.full_url).path)[-1]
+ return os.path.join(dest_dir, dest_fn)
+
+ def get_download_fn(self, scr):
+ dest_fn = self.get_build_fn(scr)
+ return os.path.join(self.build_dir, dest_fn)
+
+ def read_manifest(self, scr, fn):
+ manifest = []
+ manifest_lines = file(fn).readlines()
+ manifest_lines = [x.strip() for x in manifest_lines]
+ 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) )
+
+ 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) )
+ return manifest
+
+ def download_file(self, url, dest_fn):
+ logger.info("Download %s to %s" % (url, dest_fn))
+ 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())
+
+ # make python files executable
+ if dest_fn.endswith(".py"): # and contents.startswith("#!"):
+ os.chmod(dest_fn, 0755)
+
+ def download_resource(self, scr):
+ if scr.format == "manifest":
+ manifest_fn = self.get_download_fn(scr)
+ self.download_file(scr.full_url, manifest_fn)
+ manifest = self.read_manifest(scr, manifest_fn)
+ for (url, download_fn, build_fn) in manifest:
+ self.download_file(url, download_fn)
+ else:
+ self.download_file(scr.full_url, self.get_download_fn(scr))
+
+ def get_docker_lines(self, scr):
+ if scr.format == "manifest":
+ manifest_fn = self.get_download_fn(scr)
+ manifest = self.read_manifest(scr, manifest_fn)
+ lines = []
+ for (url, download_fn, build_fn) in manifest:
+ lines.append("ADD %s /%s" % (build_fn, build_fn))
+ return lines
+ else:
+ build_fn = self.get_build_fn(scr)
+ return ["ADD %s /%s" % (build_fn, build_fn)]
+
+ def get_controller_docker_lines(self, controller, kinds):
+ need_service_init_py = False
+ dockerfile=[]
+ for scr in controller.service_controller_resources.all():
+ if scr.kind in kinds:
+ lines = self.get_docker_lines(scr)
+ dockerfile = dockerfile + lines
+ if scr.kind in ["admin", "models"]:
+ need_service_init_py = True
+
+ if need_service_init_py:
+ file(os.path.join(self.build_dir, "opt/xos/empty__init__.py"),"w").write("")
+ dockerfile.append("ADD opt/xos/empty__init__.py /opt/xos/services/%s/__init__.py" % controller.name)
+
+ return dockerfile
+
+ def check_controller_unready(self, controller):
+ unready_resources=[]
+ for scr in controller.service_controller_resources.all():
+ if (not scr.backend_status) or (not scr.backend_status.startswith("1")):
+ unready_resources.append(scr)
+
+ return unready_resources
+
+ # stuff that has to do with building
+
+ def create_xos_app_data(self, name, dockerfile, 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 app_list:
+ 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:
+ 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):
+ dockerfile_fn = "Dockerfile.UI"
+
+ app_list = []
+ migration_list = []
+
+ dockerfile = ["FROM %s" % self.source_ui_image]
+ for controller in ServiceController.objects.all():
+ if self.check_controller_unready(controller):
+ logger.warning("Controller %s has unready resources" % str(controller))
+ continue
+
+ dockerfile = dockerfile + self.get_controller_docker_lines(controller, self.UI_KINDS)
+ if controller.service_controller_resources.filter(kind="models").exists():
+ app_list.append("services." + controller.name)
+ migration_list.append(controller.name)
+
+ self.create_xos_app_data("ui", dockerfile, app_list, migration_list)
+
+ file(os.path.join(self.build_dir, dockerfile_fn), "w").write("\n".join(dockerfile)+"\n")
+
+ return {"dockerfile_fn": dockerfile_fn,
+ "docker_image_name": "xosproject/xos-ui"}
+
+ def create_synchronizer_dockerfile(self, controller):
+ # bake in the synchronizer from this controller
+ sync_lines = self.get_controller_docker_lines(controller, self.SYNC_CONTROLLER_KINDS)
+ if not sync_lines:
+ return []
+
+ dockerfile_fn = "Dockerfile.%s" % controller.name
+ dockerfile = ["FROM %s" % self.source_sync_image]
+
+ # Now bake in models from this controller as well as the others
+ # It's important to bake all services in, because some services'
+ # synchronizers may depend on models from another service.
+ app_list = []
+ for c in ServiceController.objects.all():
+ dockerfile = dockerfile + self.get_controller_docker_lines(c, self.SYNC_ALLCONTROLLER_KINDS)
+ if controller.service_controller_resources.filter(kind="models").exists():
+ app_list.append("services." + controller.name)
+
+ self.create_xos_app_data(controller.name, dockerfile, app_list, None)
+
+ dockerfile = dockerfile + sync_lines
+ file(os.path.join(self.build_dir, dockerfile_fn), "w").write("\n".join(dockerfile)+"\n")
+
+ return {"dockerfile_fn": dockerfile_fn,
+ "docker_image_name": "xosproject/xos-synchronizer-%s" % controller.name}
+
+ def create_docker_compose(self):
+ 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})
+
+ containers = {}
+
+ containers["xos_db"] = \
+ {"image": "xosproject/xos-postgres",
+ "expose": [5432]}
+
+ db_container_name = xos.docker_project_name + "_xos_db_1"
+
+ 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": [db_container_name],
+ "volumes": volume_list}
+
+# 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,
+# "ports": {"%d"%xos.bootstrap_ui_port : "%d"%xos.bootstrap_ui_port},
+# #"external_links": [db_container_name],
+# "links": ["xos_db"],
+# "volumes": volume_list}
+
+ for c in ServiceController.objects.all():
+ if self.check_controller_unready(c):
+ logger.warning("Controller %s has unready resources" % str(c))
+ continue
+
+ containers["xos_synchronizer_%s" % c.name] = \
+ {"image": "xosproject/xos-synchronizer-%s" % c.name,
+ "command": 'bash -c "sleep 120; cd /opt/xos/synchronizers/%s; bash ./run.sh"' % c.name,
+ #"external_links": [db_container_name],
+ "links": ["xos_db"],
+ "volumes": volume_list}
+
+ 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=[]
+# dockerfiles.append(self.create_ui_dockerfile())
+#
+# for controller in ServiceController.objects.all():
+# dockerfiles.append(self.create_synchronizer_dockerfile(controller))
+
+
+
diff --git a/xos/synchronizers/openstack/steps/purge_disabled_users.py b/xos/synchronizers/openstack/steps/purge_disabled_users.py
index 0973b8c..6b1dac3 100644
--- a/xos/synchronizers/openstack/steps/purge_disabled_users.py
+++ b/xos/synchronizers/openstack/steps/purge_disabled_users.py
@@ -7,19 +7,19 @@
from core.models.user import User
from xos.logger import observer_logger as logger
-class SyncRoles(OpenStackSyncStep):
- provides=[User]
- requested_interval=0
- observes=User
-
- def fetch_pending(self, deleted):
- if (deleted):
- # users marked as deleted
- return User.deleted_objects.all()
- else:
- # disabled users that haven't been updated in over a week
- one_week_ago = datetime.datetime.now() - datetime.timedelta(days=7)
- return User.objects.filter(is_active=False, updated__gt=one_week_ago)
-
- def sync_record(self, user):
- user.delete()
+#class SyncRoles(OpenStackSyncStep):
+# provides=[User]
+# requested_interval=0
+# observes=User
+#
+# def fetch_pending(self, deleted):
+# if (deleted):
+# # users marked as deleted
+# return User.deleted_objects.all()
+# else:
+# # disabled users that haven't been updated in over a week
+# one_week_ago = datetime.datetime.now() - datetime.timedelta(days=7)
+# return User.objects.filter(is_active=False, updated__gt=one_week_ago)
+#
+# def sync_record(self, user):
+# user.delete()
diff --git a/xos/tools/rebuild.py b/xos/tools/rebuild.py
new file mode 100755
index 0000000..dc2c482
--- /dev/null
+++ b/xos/tools/rebuild.py
@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+
+import os
+import sys
+sys.path.append("/opt/xos")
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "xos.settings")
+import django
+from core.models import XOS
+django.setup()
+
+xoses = XOS.objects.all()
+if not xoses:
+ print "There is no XOS model"
+
+for xos in xoses:
+ xos.rebuild()
+
diff --git a/xos/tosca/custom_types/exampleservice.m4 b/xos/tosca/custom_types/exampleservice.m4._unused
similarity index 100%
copy from xos/tosca/custom_types/exampleservice.m4
copy to xos/tosca/custom_types/exampleservice.m4._unused
diff --git a/xos/tosca/custom_types/exampleservice.yaml b/xos/tosca/custom_types/exampleservice.yaml._unused
similarity index 100%
copy from xos/tosca/custom_types/exampleservice.yaml
copy to xos/tosca/custom_types/exampleservice.yaml._unused
diff --git a/xos/tosca/custom_types/xos.m4 b/xos/tosca/custom_types/xos.m4
index 109fc1d..9497b6d 100644
--- a/xos/tosca/custom_types/xos.m4
+++ b/xos/tosca/custom_types/xos.m4
@@ -6,6 +6,43 @@
include(macros.m4)
node_types:
+ tosca.nodes.XOS:
+ derived_from: tosca.nodes.Root
+ description: The root of XOS
+ properties:
+ xos_base_props
+ ui_port:
+ type: integer
+ required: false
+ description: TCP port of user interface
+ bootstrap_ui_port:
+ type: integer
+ required: false
+ descrption: TCP port of bootstrap user interface
+ docker_project_name:
+ type: string
+ required: false
+ description: Docker project name
+ enable_build:
+ type: boolean
+ required: false
+ description: True if XOS build should be enabled
+
+
+ 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: >
@@ -17,6 +54,68 @@
xos_base_props
xos_base_service_props
+ tosca.nodes.ServiceController:
+ derived_from: tosca.nodes.Root
+ description: >
+ An XOS Service Controller.
+ properties:
+ xos_base_props
+ base_url:
+ type: string
+ required: false
+ description: Base url, to allow resources to use relative URLs
+ models:
+ type: string
+ required: false
+ description: url of models.py
+ admin:
+ type: string
+ required: false
+ description: url of admin.py
+ synchronizer:
+ type: string
+ required: false
+ description: url of synchronizer manifest
+ tosca_custom_types:
+ type: string
+ required: false
+ description: url of tosca custom_types
+ rest_service:
+ type: string
+ required: false
+ description: url of REST API service file
+ rest_tenant:
+ type: string
+ required: false
+ description: url of REST API tenant file
+ private_key:
+ type: string
+ required: false
+ description: private key
+ public_key:
+ type: string
+ required: false
+ description: public key
+
+ tosca.nodes.ServiceControllerResource:
+ derived_from: tosca.nodes.Root
+ description: >
+ An XOS Service Resource.
+ properties:
+ xos_base_props
+ kind:
+ type: string
+ required: false
+ description: models, admin, django_library, synchronizer, rest, tosca_custom_types, or tosca_resource
+ format:
+ type: string
+ required: false
+ description: python, manifest, or docker
+ url:
+ type: string
+ required: false
+ description: url of resource, may be relative to base_url or absolute
+
tosca.nodes.Tenant:
derived_from: tosca.nodes.Root
description: >
@@ -1034,6 +1133,15 @@
tosca.relationships.UsesAgent:
derived_from: tosca.relationships.Root
+ tosca.relationships.HasResource:
+ derived_from: tosca.relationships.Root
+
+ 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 8b4c669..66229d5 100644
--- a/xos/tosca/custom_types/xos.yaml
+++ b/xos/tosca/custom_types/xos.yaml
@@ -21,6 +21,73 @@
node_types:
+ tosca.nodes.XOS:
+ derived_from: tosca.nodes.Root
+ description: The root of XOS
+ 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
+ ui_port:
+ type: integer
+ required: false
+ description: TCP port of user interface
+ bootstrap_ui_port:
+ type: integer
+ required: false
+ descrption: TCP port of bootstrap user interface
+ docker_project_name:
+ type: string
+ required: false
+ description: Docker project name
+ enable_build:
+ type: boolean
+ required: false
+ description: True if XOS build should be enabled
+
+
+ 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: >
@@ -80,6 +147,98 @@
required: false
description: Version number of Service.
+ tosca.nodes.ServiceController:
+ derived_from: tosca.nodes.Root
+ description: >
+ An XOS Service 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
+ replaces:
+ type: string
+ required: false
+ descrption: Replaces/renames this object
+ base_url:
+ type: string
+ required: false
+ description: Base url, to allow resources to use relative URLs
+ models:
+ type: string
+ required: false
+ description: url of models.py
+ admin:
+ type: string
+ required: false
+ description: url of admin.py
+ synchronizer:
+ type: string
+ required: false
+ description: url of synchronizer manifest
+ tosca_custom_types:
+ type: string
+ required: false
+ description: url of tosca custom_types
+ rest_service:
+ type: string
+ required: false
+ description: url of REST API service file
+ rest_tenant:
+ type: string
+ required: false
+ description: url of REST API tenant file
+ private_key:
+ type: string
+ required: false
+ description: private key
+ public_key:
+ type: string
+ required: false
+ description: public key
+
+ tosca.nodes.ServiceControllerResource:
+ derived_from: tosca.nodes.Root
+ description: >
+ An XOS Service Resource.
+ 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
+ kind:
+ type: string
+ required: false
+ description: models, admin, django_library, synchronizer, rest, tosca_custom_types, or tosca_resource
+ format:
+ type: string
+ required: false
+ description: python, manifest, or docker
+ url:
+ type: string
+ required: false
+ description: url of resource, may be relative to base_url or absolute
+
tosca.nodes.Tenant:
derived_from: tosca.nodes.Root
description: >
@@ -881,6 +1040,8 @@
required: false
description: list of access devices, in format "uplink vlan", multiple entries separated by commas
+# XXX - uncomment if we want access device to be specified as separate Tosca
+# objects, rather than encoding them into VOLTDevice.access_devices
# tosca.nodes.AccessDevice:
# derived_from: tosca.nodes.Root
# description: >
@@ -1856,6 +2017,18 @@
tosca.relationships.MemberOfDevice:
derived_from: tosca.relationships.Root
+ tosca.relationships.UsesAgent:
+ derived_from: tosca.relationships.Root
+
+ tosca.relationships.HasResource:
+ derived_from: tosca.relationships.Root
+
+ 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/exampleservice.py b/xos/tosca/resources/exampleservice._unused
similarity index 100%
rename from xos/tosca/resources/exampleservice.py
rename to xos/tosca/resources/exampleservice._unused
diff --git a/xos/tosca/resources/exampletenant.py b/xos/tosca/resources/exampletenant._unused
similarity index 100%
rename from xos/tosca/resources/exampletenant.py
rename to xos/tosca/resources/exampletenant._unused
diff --git a/xos/tosca/resources/servicecontroller.py b/xos/tosca/resources/servicecontroller.py
new file mode 100644
index 0000000..34b95c2
--- /dev/null
+++ b/xos/tosca/resources/servicecontroller.py
@@ -0,0 +1,42 @@
+import os
+import pdb
+import sys
+import tempfile
+sys.path.append("/opt/tosca")
+from translator.toscalib.tosca_template import ToscaTemplate
+
+from core.models import ServiceController, ServiceControllerResource
+
+from xosresource import XOSResource
+
+class XOSServiceController(XOSResource):
+ provides = "tosca.nodes.ServiceController"
+ xos_model = ServiceController
+ copyin_props = ["base_url"]
+
+ def postprocess_resource_prop(self, obj, kind, format):
+ value = self.get_property(kind)
+ if value:
+ scr = ServiceControllerResource.objects.filter(service_controller=obj, kind=kind, format=format)
+ if scr:
+ scr=scr[0]
+ if scr.url != value:
+ self.info("updating resource %s" % kind)
+ scr.url = value
+ scr.save()
+ else:
+ self.info("adding resource %s" % kind)
+ scr = ServiceControllerResource(service_controller=obj, name=kind, kind=kind, format=format, url=value)
+ scr.save()
+
+ def postprocess(self, obj):
+ # allow these common resource to be specified directly by the ServiceController tosca object
+ self.postprocess_resource_prop(obj, "models", "python")
+ self.postprocess_resource_prop(obj, "admin", "python")
+ self.postprocess_resource_prop(obj, "tosca_custom_types", "yaml")
+ self.postprocess_resource_prop(obj, "synchronizer", "manifest")
+ self.postprocess_resource_prop(obj, "private_key", "raw")
+ self.postprocess_resource_prop(obj, "public_key", "raw")
+ self.postprocess_resource_prop(obj, "rest_service", "python")
+ self.postprocess_resource_prop(obj, "rest_tenant", "python")
+
diff --git a/xos/tosca/resources/servicecontrollerresource.py b/xos/tosca/resources/servicecontrollerresource.py
new file mode 100644
index 0000000..96ea83d
--- /dev/null
+++ b/xos/tosca/resources/servicecontrollerresource.py
@@ -0,0 +1,27 @@
+import os
+import pdb
+import sys
+import tempfile
+sys.path.append("/opt/tosca")
+from translator.toscalib.tosca_template import ToscaTemplate
+
+from core.models import ServiceControllerResource, ServiceController
+
+from xosresource import XOSResource
+
+class XOSServiceControllerResource(XOSResource):
+ provides = "tosca.nodes.ServiceControllerResource"
+ xos_model = ServiceControllerResource
+ copyin_props = ["kind", "format", "url"]
+
+ def get_xos_args(self, throw_exception=True):
+ args = super(XOSServiceControllerResource, self).get_xos_args()
+
+ controller_name = self.get_requirement("tosca.relationships.UsedByController", throw_exception=throw_exception)
+ if controller_name:
+ args["service_controller"] = self.get_xos_object(ServiceController, throw_exception=throw_exception, name=controller_name)
+
+ return args
+
+
+
diff --git a/xos/tosca/resources/xosmodel.py b/xos/tosca/resources/xosmodel.py
new file mode 100644
index 0000000..188bb4f
--- /dev/null
+++ b/xos/tosca/resources/xosmodel.py
@@ -0,0 +1,30 @@
+import os
+import pdb
+import sys
+import tempfile
+sys.path.append("/opt/tosca")
+from translator.toscalib.tosca_template import ToscaTemplate
+
+from core.models import XOS, XOSVolume
+
+from xosresource import XOSResource
+
+class XOSXOS(XOSResource):
+ provides = "tosca.nodes.XOS"
+ xos_model = XOS
+ copyin_props = ["ui_port", "bootstrap_ui_port", "docker_project_name", "enable_build"]
+
+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
diff --git a/xos/xos/settings.py b/xos/xos/settings.py
index 7835689..9f20937 100644
--- a/xos/xos/settings.py
+++ b/xos/xos/settings.py
@@ -197,6 +197,13 @@
'rest_framework_swagger',
)
+# add services that were configured by xosbuilder to INSTALLED_APPS
+if os.path.exists("/opt/xos/xos/xosbuilder_app_list"):
+ for line in file("/opt/xos/xos/xosbuilder_app_list").readlines():
+ line = line.strip()
+ if line:
+ INSTALLED_APPS = list(INSTALLED_APPS) + [line]
+
if DJANGO_VERSION[1] >= 7:
# if django >= 1.7, then change the admin module
INSTALLED_APPS = list(INSTALLED_APPS)