Merge branch 'master' of github.com:open-cloud/xos
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/mydeployment.yaml b/xos/configurations/common/mydeployment.yaml
index 66bb75d..c81fd93 100644
--- a/xos/configurations/common/mydeployment.yaml
+++ b/xos/configurations/common/mydeployment.yaml
@@ -16,9 +16,15 @@
m1.small:
type: tosca.nodes.Flavor
+ m1.xlarge:
+ type: tosca.nodes.Flavor
+
MyDeployment:
type: tosca.nodes.Deployment
requirements:
+ - m1.xlarge:
+ node: m1.large
+ relationship: tosca.relationships.SupportsFlavor
- m1.large:
node: m1.large
relationship: tosca.relationships.SupportsFlavor
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..c8f4574 100644
--- a/xos/configurations/cord-pod/Makefile
+++ b/xos/configurations/cord-pod/Makefile
@@ -1,27 +1,53 @@
+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
+
+fabric: fabric.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/fabric.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
+ sudo cp id_rsa key_import/exampleservice_rsa
+ sudo cp id_rsa.pub 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 81 xos
+ bash ../common/wait_for_xos_port.sh 80
+ sudo docker-compose -p $(DOCKER_PROJECT) -f $(DOCKER_COMPOSE_YML) run xos_ui python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/pod-exampleservice.yaml
cord-ceilometer: ceilometer_custom_images cord
sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/ceilometer.yaml
@@ -35,6 +61,9 @@
vtn-external.yaml:
export SETUPDIR=.; bash ./make-vtn-external-yaml.sh
+fabric.yaml:
+ export SETUPDIR=.; bash ./make-fabric-yaml.sh
+
virtualbng_json:
export SETUPDIR=.; bash ./make-virtualbng-json.sh
@@ -42,10 +71,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 +111,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/cord-vtn-vsg.yaml b/xos/configurations/cord-pod/cord-vtn-vsg.yaml
index 8c73799..44d4fbb 100644
--- a/xos/configurations/cord-pod/cord-vtn-vsg.yaml
+++ b/xos/configurations/cord-pod/cord-vtn-vsg.yaml
@@ -69,21 +69,6 @@
node: addresses_exampleservice-public
relationship: tosca.relationships.ProvidesAddresses
- service#fabric:
- type: tosca.nodes.FabricService
- properties:
- view_url: /admin/fabric/fabricservice/$id$/
- replaces: service_fabric
-
- service#ONOS_Fabric:
- type: tosca.nodes.ONOSService
- requirements:
- properties:
- kind: onos
- view_url: /admin/onos/onosservice/$id$/
- no_container: true
- rest_hostname: onos-fabric
- replaces: service_ONOS_Fabric
service#ONOS_CORD:
type: tosca.nodes.ONOSService
@@ -92,6 +77,13 @@
no-create: true
no-update: true
+ service#ONOS_Fabric:
+ type: tosca.nodes.ONOSService
+ properties:
+ no-delete: true
+ no-create: true
+ no-update: true
+
vOLT_ONOS_app:
type: tosca.nodes.ONOSvOLTApp
requirements:
diff --git a/xos/configurations/cord-pod/docker-compose.yml b/xos/configurations/cord-pod/docker-compose-bootstrap.yml
similarity index 74%
rename from xos/configurations/cord-pod/docker-compose.yml
rename to xos/configurations/cord-pod/docker-compose-bootstrap.yml
index fa8660a..9f17c42 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,23 +119,37 @@
max-size: "100k"
max-file: "5"
-xos:
- command: python /opt/xos/manage.py runserver 0.0.0.0:80 --insecure --makemigrations
- image: xosproject/xos
+xos_synchronizer_fabric:
+ image: xosproject/xos-synchronizer-openstack
+ command: bash -c "sleep 120; python /opt/xos/synchronizers/fabric/fabric-synchronizer.py -C /opt/xos/synchronizers/fabric/fabric_synchronizer_config"
+ labels:
+ org.xosproject.kind: synchronizer
+ org.xosproject.target: fabric
links:
- xos_db
- ports:
- - "80:80"
volumes:
- .:/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
log_driver: "json-file"
log_opt:
max-size: "100k"
max-file: "5"
+xos_bootstrap_ui:
+ command: python /opt/xos/manage.py runserver 0.0.0.0:81 --insecure --makemigrations
+ image: xosproject/xos
+ links:
+ - xos_db
+ ports:
+ - "81:81"
+ volumes:
+# - .:/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
+ log_driver: "json-file"
+ log_opt:
+ max-size: "100k"
+ max-file: "5"
diff --git a/xos/configurations/cord-pod/make-fabric-yaml.sh b/xos/configurations/cord-pod/make-fabric-yaml.sh
new file mode 100644
index 0000000..a829690
--- /dev/null
+++ b/xos/configurations/cord-pod/make-fabric-yaml.sh
@@ -0,0 +1,71 @@
+FN=$SETUPDIR/fabric.yaml
+
+rm -f $FN
+
+cat >> $FN <<EOF
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+imports:
+ - custom_types/xos.yaml
+
+description: generate fabric configuration
+
+topology_template:
+ node_templates:
+
+ service#ONOS_Fabric:
+ type: tosca.nodes.ONOSService
+ requirements:
+ properties:
+ kind: onos
+ view_url: /admin/onos/onosservice/\$id$/
+ no_container: true
+ rest_hostname: onos-fabric
+ replaces: service_ONOS_Fabric
+
+ service#fabric:
+ type: tosca.nodes.FabricService
+ properties:
+ view_url: /admin/fabric/fabricservice/\$id\$/
+ replaces: service_fabric
+
+
+EOF
+
+NODES=$( bash -c "source $SETUPDIR/admin-openrc.sh ; nova host-list" |grep compute|awk '{print $2}' )
+I=0
+for NODE in $NODES; do
+ echo $NODE
+ cat >> $FN <<EOF
+ $NODE:
+ type: tosca.nodes.Node
+
+ # Fabric location field for node $NODE
+ ${NODE}_location_tag:
+ type: tosca.nodes.Tag
+ properties:
+ name: location
+ value: of:0000000000000001/1
+ requirements:
+ - target:
+ node: $NODE
+ relationship: tosca.relationships.TagsObject
+ - service:
+ node: service#ONOS_Fabric
+ relationship: tosca.relationships.MemberOfService
+EOF
+done
+
+cat >> $FN <<EOF
+ Fabric_ONOS_app:
+ type: tosca.nodes.ONOSApp
+ requirements:
+ - onos_tenant:
+ node: service#ONOS_Fabric
+ relationship: tosca.relationships.TenantOfService
+ - fabric_service:
+ node: service#fabric
+ relationship: tosca.relationships.UsedByService
+ properties:
+ dependencies: org.onosproject.lldpprovider, org.onosproject.hostprovider, org.onosproject.openflow-base, org.onosproject.openflow, org.onosproject.drivers, org.onosproject.segmentrouting
+EOF
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..3975893
--- /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 "cd /opt/xos/synchronizers/onboarding; ./run.sh"
+ #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/configurations/mcord/Makefile b/xos/configurations/mcord/Makefile
index 7f4d9a5..53fec7b 100644
--- a/xos/configurations/mcord/Makefile
+++ b/xos/configurations/mcord/Makefile
@@ -31,6 +31,9 @@
enter-vbbu:
sudo docker exec -it mcord_xos_synchronizer_vbbu_1 bash
+enter-vpgwc:
+ sudo docker exec -it mcord_xos_synchronizer_vpgwc_1 bash
+
upgrade_pkgs:
sudo pip install httpie --upgrade
diff --git a/xos/configurations/mcord/docker-compose.yml b/xos/configurations/mcord/docker-compose.yml
index 8598396..367b168 100644
--- a/xos/configurations/mcord/docker-compose.yml
+++ b/xos/configurations/mcord/docker-compose.yml
@@ -40,6 +40,25 @@
- "compute9:10.102.81.9"
- "compute10:10.102.81.10"
+xos_synchronizer_vpgwc:
+ image: xosproject/xos-synchronizer-openstack
+ command: bash -c "sleep 120; python /opt/xos/synchronizers/vpgwc/vpgwc-synchronizer.py -C /opt/xos/synchronizers/vpgwc/vpgwc_config"
+ labels:
+ org.xosproject.kind: synchronizer
+ org.xosproject.target: vpgwc
+ links:
+ - xos_db
+ volumes:
+ - ../setup/id_rsa_mcord:/opt/xos/configurations/mcord/mcord_private_key:ro # private key
+ - ../setup/id_rsa_mcord.pub:/opt/xos/configurations/mcord/mcord_public_key:ro # public key
+ - ../setup:/root/setup:ro
+ extra_hosts:
+ - "controller:10.102.81.3"
+ - "computeBBU1:10.102.81.6"
+ - "computeBBU2:10.102.81.7"
+ - "compute9:10.102.81.9"
+ - "compute10:10.102.81.10"
+
# FUTURE
#xos_swarm_synchronizer:
# image: xosproject/xos-swarm-synchronizer
diff --git a/xos/configurations/mcord/mcord.yaml b/xos/configurations/mcord/mcord.yaml
index 42241f0..450bd23 100644
--- a/xos/configurations/mcord/mcord.yaml
+++ b/xos/configurations/mcord/mcord.yaml
@@ -92,6 +92,25 @@
default: New vBBU Component
description: Just a message
+ tosca.nodes.VPGWCComponent:
+ derived_from: tosca.nodes.Root
+ description: >
+ CORD: vPGWC Component of MCORD Service.
+ properties:
+ kind:
+ type: string
+ default: VPGWC_KIND
+ description: Kind of component
+ s5s8_pgw_tag:
+ type: string
+ required: false
+ default: 300
+ description: VTN stag port-name
+ display_message:
+ type: string
+ required: false
+ default: New vPGWc Component
+ description: Just a message
topology_template:
node_templates:
@@ -107,6 +126,18 @@
artifacts:
pubkey: /opt/xos/configurations/mcord/mcord_public_key
+ vPGWC:
+ type: tosca.nodes.MCORDService
+ requirements:
+ properties:
+ kind: vEPC
+ icon_url: /static/mCordServices/service_server.png
+ view_url: /admin/mcord/vpgwccomponent
+ public_key: { get_artifact: [ SELF, pubkey, LOCAL_FILE] }
+ private_key_fn: /opt/xos/configurations/mcord/mcord_private_key
+ artifacts:
+ pubkey: /opt/xos/configurations/mcord/mcord_public_key
+
m1.xlarge:
type: tosca.nodes.Flavor
@@ -189,12 +220,35 @@
node: mysite_vbbu_slice1
relationship: tosca.relationships.ConnectsToSlice
+ lan_3gpp_s5s8_pgw_network:
+ type: tosca.nodes.network.Network.XOS
+ properties:
+ ip_version: 4
+ labels: lan_3gpp_s5s8_pgw_net
+ cidr: 172.17.1.0/24
+ start_ip: 172.17.1.2
+ end_ip: 172.17.1.8
+ gateway_ip: 172.17.1.1
+ requirements:
+ - network_template:
+ node: External
+ relationship: tosca.relationships.UsesNetworkTemplate
+ - owner:
+ node: mysite_mobile_net
+ relationship: tosca.relationships.MemberOfSlice
+ - connection:
+ node: mysite_vpgwc_slice1
+ relationship: tosca.relationships.ConnectsToSlice
+
mysite:
type: tosca.nodes.Site
mcord-bbu-multi-nic:
type: tosca.nodes.Image
+ mcord-vpgwc-onos-multi-nic:
+ type: tosca.nodes.Image
+
mysite_management:
description: This slice exists solely to own the management network
type: tosca.nodes.Slice
@@ -238,4 +292,41 @@
network: noauto
# default_flavor: m1.xlarge
default_node: computeBBU2
-
+
+ mysite_vpgwc_slice1:
+ description: vPGWC Service Slice 1
+ type: tosca.nodes.Slice
+ requirements:
+ - vPGWC:
+ node: vPGWC
+ relationship: tosca.relationships.MemberOfService
+ - site:
+ node: mysite
+ relationship: tosca.relationships.MemberOfSite
+ - default_image:
+ node: mcord-vpgwc-onos-multi-nic
+ relationship: tosca.relationships.DefaultImage
+ - default_flavor:
+ node: m1.xlarge
+ relationship: tosca.relationships.DefaultFlavor
+ - management:
+ node: management
+ relationship: tosca.relationships.ConnectsToNetwork
+ properties:
+ network: noauto
+ default_node: compute10
+
+ mysite_VPGWC_Component:
+ description: MCORD Service default Component
+ type: tosca.nodes.VPGWCComponent
+ requirements:
+ - provider_service:
+ node: vPGWC
+ relationship: tosca.relationships.MemberOfService
+ - vpgwc_slice:
+ node: mysite_vpgwc_slice1
+ relationship: tosca.relationships.MemberOfSlice
+ properties:
+ display_message: vPGWC looks good!
+ s5s8_pgw_tag: 300
+
diff --git a/xos/configurations/mcord/migrations/0001_initial.py b/xos/configurations/mcord/migrations/0001_initial.py
index c53e548..a11fe30 100644
--- a/xos/configurations/mcord/migrations/0001_initial.py
+++ b/xos/configurations/mcord/migrations/0001_initial.py
@@ -31,4 +31,14 @@
},
bases=('core.tenantwithcontainer',),
),
+ migrations.CreateModel(
+ name='VPGWCComponent',
+ fields=[
+ ],
+ options={
+ 'verbose_name': 'VPGWC MCORD Service Component',
+ 'proxy': True,
+ },
+ bases=('core.tenantwithcontainer',),
+ ),
]
diff --git a/xos/configurations/mcord/nodes.yaml b/xos/configurations/mcord/nodes.yaml
index ae22112..48e7247 100644
--- a/xos/configurations/mcord/nodes.yaml
+++ b/xos/configurations/mcord/nodes.yaml
@@ -22,3 +22,23 @@
node: MyDeployment
relationship: tosca.relationships.MemberOfDeployment
+ nova-compute:
+ type: tosca.nodes.Node
+ requirements:
+ - site:
+ node: mysite
+ relationship: tosca.relationships.MemberOfSite
+ - deployment:
+ node: MyDeployment
+ relationship: tosca.relationships.MemberOfDeployment
+
+ compute10:
+ type: tosca.nodes.Node
+ requirements:
+ - site:
+ node: mysite
+ relationship: tosca.relationships.MemberOfSite
+ - deployment:
+ node: MyDeployment
+ relationship: tosca.relationships.MemberOfDeployment
+
diff --git a/xos/configurations/mcord/setup.yaml b/xos/configurations/mcord/setup.yaml
index 0dd2769..9db865e 100644
--- a/xos/configurations/mcord/setup.yaml
+++ b/xos/configurations/mcord/setup.yaml
@@ -166,12 +166,6 @@
icon_url: /static/mCordServices/service_server.png
kind: vEPC
- vPGW:
- type: tosca.nodes.Service
- properties:
- view_url: /mcord/?service=vPGW
- icon_url: /static/mCordServices/service_server.png
- kind: vEPC
# EDGE
Cache:
@@ -223,10 +217,10 @@
icon_url: /static/mCordServices/service_server.png
kind: vEPC
- vPGW:
+ vPGWC:
type: tosca.nodes.Service
properties:
- view_url: /mcord/?service=vPGW
+ view_url: /mcord/?service=vPGWC
icon_url: /static/mCordServices/service_server.png
kind: vEPC
diff --git a/xos/configurations/mcord/vpgwc.yaml b/xos/configurations/mcord/vpgwc.yaml
new file mode 100644
index 0000000..d003bb2
--- /dev/null
+++ b/xos/configurations/mcord/vpgwc.yaml
@@ -0,0 +1,203 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: Setup MCORD-related services.
+
+imports:
+ - custom_types/xos.yaml
+
+node_types:
+
+ tosca.nodes.MCORDService:
+ derived_from: tosca.nodes.Root
+ description: >
+ An XOS Service object. Services may be listed in the Service
+ directory and may be linked together via Tenancy Relationships.
+ capabilities:
+ scalable:
+ type: tosca.capabilities.Scalable
+ service:
+ type: tosca.capabilities.xos.Service
+ 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
+ kind:
+ type: string
+ default: VPGWC_KIND
+ 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.
+
+ tosca.nodes.VPGWCComponent:
+ derived_from: tosca.nodes.Root
+ description: >
+ CORD: vPGWC Component of MCORD Service.
+ properties:
+ kind:
+ type: string
+ default: VPGWC_KIND
+ description: Kind of component
+ s5s8_pgw_tag:
+ type: string
+ required: false
+ default: 300
+ description: VTN stag port-name
+ display_message:
+ type: string
+ required: false
+ default: New vPGWC Component
+ description: Just a message
+
+
+topology_template:
+ node_templates:
+ vPGWC:
+ type: tosca.nodes.MCORDService
+ requirements:
+ properties:
+ kind: VPGWC_KIND
+ icon_url: /static/mCordServices/service_server.png
+ view_url: /admin/mcord/vpgwccomponent
+ public_key: { get_artifact: [ SELF, pubkey, LOCAL_FILE] }
+ private_key_fn: /opt/xos/configurations/mcord/mcord_private_key
+ artifacts:
+ pubkey: /opt/xos/configurations/mcord/mcord_public_key
+
+ m1.xlarge:
+ type: tosca.nodes.Flavor
+
+ Private:
+ type: tosca.nodes.NetworkTemplate
+
+ External:
+ type: tosca.nodes.NetworkTemplate
+
+ management_template:
+ type: tosca.nodes.NetworkTemplate
+ properties:
+ visibility: private
+ translation: none
+
+ management:
+ type: tosca.nodes.network.Network.XOS
+# properties:
+# no-create: true
+# no-delete: true
+# no-update: true
+
+ lan_3gpp_s5s8_pgw_network:
+ type: tosca.nodes.network.Network.XOS
+ properties:
+ ip_version: 4
+ labels: lan_3gpp_s5s8_pgw_net
+ cidr: 172.17.1.0/24
+ start_ip: 172.17.1.2
+ end_ip: 172.17.1.8
+ gateway_ip: 172.17.1.1
+ requirements:
+ - network_template:
+ node: External
+ relationship: tosca.relationships.UsesNetworkTemplate
+ - owner:
+ node: mysite_mobile_net
+ relationship: tosca.relationships.MemberOfSlice
+ - connection:
+ node: mysite_vpgwc_slice1
+ relationship: tosca.relationships.ConnectsToSlice
+
+ mysite:
+ type: tosca.nodes.Site
+
+ mcord-vpgwc-onos-multi-nic:
+ type: tosca.nodes.Image
+
+ mysite_management:
+ description: This slice exists solely to own the management network
+ type: tosca.nodes.Slice
+ properties:
+ network: noauto
+ requirements:
+ - site:
+ node: mysite
+ relationship: tosca.relationships.MemberOfSite
+
+ mysite_mobile_net:
+ description: This slice exists solely to own the mobile network
+ type: tosca.nodes.Slice
+ properties:
+ network: noauto
+ requirements:
+ - site:
+ node: mysite
+ relationship: tosca.relationships.MemberOfSite
+
+ mysite_vpgwc_slice1:
+ description: vPGWC Service Slice 1
+ type: tosca.nodes.Slice
+ requirements:
+ - vPGWC:
+ node: vPGWC
+ relationship: tosca.relationships.MemberOfService
+ - site:
+ node: mysite
+ relationship: tosca.relationships.MemberOfSite
+ - default_image:
+ node: mcord-vpgwc-onos-multi-nic
+ relationship: tosca.relationships.DefaultImage
+ - default_flavor:
+ node: m1.xlarge
+ relationship: tosca.relationships.DefaultFlavor
+ - management:
+ node: management
+ relationship: tosca.relationships.ConnectsToNetwork
+ properties:
+ network: noauto
+ default_node: compute10
+
+ mysite_VPGWC_Component:
+ description: MCORD Service default Component
+ type: tosca.nodes.VPGWCComponent
+ requirements:
+ - provider_service:
+ node: vPGWC
+ relationship: tosca.relationships.MemberOfService
+ - vpgwc_slice:
+ node: mysite_vpgwc_slice1
+ relationship: tosca.relationships.MemberOfSlice
+ properties:
+ display_message: vPGWC looks good!
+ s5s8_pgw_tag: 300
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..9999a38
--- /dev/null
+++ b/xos/onboard/exampleservice/exampleservice-onboard.yaml
@@ -0,0 +1,25 @@
+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
+ tosca_resource: tosca/resources/exampleservice.py, tosca/resources/exampletenant.py
+ 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/tosca/resources/exampleservice.py b/xos/onboard/exampleservice/tosca/resources/exampleservice.py
similarity index 100%
rename from xos/tosca/resources/exampleservice.py
rename to xos/onboard/exampleservice/tosca/resources/exampleservice.py
diff --git a/xos/tosca/resources/exampletenant.py b/xos/onboard/exampleservice/tosca/resources/exampletenant.py
similarity index 100%
rename from xos/tosca/resources/exampletenant.py
rename to xos/onboard/exampleservice/tosca/resources/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/fabric/admin.py b/xos/services/fabric/admin.py
index 5dc5923..e372a7d 100644
--- a/xos/services/fabric/admin.py
+++ b/xos/services/fabric/admin.py
@@ -35,7 +35,7 @@
verbose_name_plural = "Fabric Services"
list_display = ("backend_status_icon", "name", "enabled")
list_display_links = ('backend_status_icon', 'name', )
- fieldsets = [(None, {'fields': ['backend_status_text', 'name','enabled','versionNumber', 'description', "view_url", "icon_url", ],
+ fieldsets = [(None, {'fields': ['backend_status_text', 'name','enabled','versionNumber', 'description', "view_url", "icon_url", "autoconfig", ],
'classes':['suit-tab suit-tab-general']})]
readonly_fields = ('backend_status_text', )
inlines = [SliceInline,ServiceAttrAsTabInline,ServicePrivilegeInline]
@@ -60,4 +60,3 @@
return FabricService.get_service_objects_by_user(request.user)
admin.site.register(FabricService, FabricServiceAdmin)
-
diff --git a/xos/services/fabric/models.py b/xos/services/fabric/models.py
index 0bf6a14..bd37416 100644
--- a/xos/services/fabric/models.py
+++ b/xos/services/fabric/models.py
@@ -1,30 +1,16 @@
from django.db import models
-from core.models import Service, PlCoreBase, Slice, Instance, Tenant, TenantWithContainer, Node, Image, User, Flavor, Subscriber, NetworkParameter, NetworkParameterType, Port, AddressPool
-from core.models.plcorebase import StrippedCharField
-import os
-from django.db import models, transaction
-from django.forms.models import model_to_dict
-from django.db.models import Q
-from operator import itemgetter, attrgetter, methodcaller
-from core.models import Tag
-from core.models.service import LeastLoadedNodeScheduler
+from core.models import Service
import traceback
from xos.exceptions import *
from xos.config import Config
-class ConfigurationError(Exception):
- pass
-
FABRIC_KIND = "fabric"
-CORD_USE_VTN = getattr(Config(), "networking_use_vtn", False)
-
class FabricService(Service):
KIND = FABRIC_KIND
class Meta:
app_label = "fabric"
verbose_name = "Fabric Service"
- proxy = True
-
+ autoconfig = models.BooleanField(default=True, help_text="Autoconfigure the fabric")
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/fabric/fabric-synchronizer.py b/xos/synchronizers/fabric/fabric-synchronizer.py
new file mode 100755
index 0000000..84bec4f
--- /dev/null
+++ b/xos/synchronizers/fabric/fabric-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/fabric/fabric_synchronizer_config b/xos/synchronizers/fabric/fabric_synchronizer_config
new file mode 100644
index 0000000..2ed56fe
--- /dev/null
+++ b/xos/synchronizers/fabric/fabric_synchronizer_config
@@ -0,0 +1,23 @@
+# Required by XOS
+[db]
+name=xos
+user=postgres
+password=password
+host=localhost
+port=5432
+
+# Required by XOS
+[api]
+nova_enabled=True
+
+# Sets options for the synchronizer
+[observer]
+name=fabric
+dependency_graph=/opt/xos/synchronizers/fabric/model-deps
+steps_dir=/opt/xos/synchronizers/fabric/steps
+sys_dir=/opt/xos/synchronizers/fabric/sys
+logfile=console
+pretend=False
+backoff_disabled=True
+save_ansible_output=True
+proxy_ssh=False
diff --git a/xos/synchronizers/exampleservice/model-deps b/xos/synchronizers/fabric/model-deps
similarity index 100%
copy from xos/synchronizers/exampleservice/model-deps
copy to xos/synchronizers/fabric/model-deps
diff --git a/xos/synchronizers/fabric/run.sh b/xos/synchronizers/fabric/run.sh
new file mode 100755
index 0000000..4e0c214
--- /dev/null
+++ b/xos/synchronizers/fabric/run.sh
@@ -0,0 +1,2 @@
+export XOS_DIR=/opt/xos
+python fabric-synchronizer.py -C $XOS_DIR/synchronizers/fabric/fabric_synchronizer_config
diff --git a/xos/synchronizers/fabric/start.sh b/xos/synchronizers/fabric/start.sh
new file mode 100755
index 0000000..8d02bf3
--- /dev/null
+++ b/xos/synchronizers/fabric/start.sh
@@ -0,0 +1,2 @@
+export XOS_DIR=/opt/xos
+nohup python fabric-synchronizer.py -C $XOS_DIR/synchronizers/fabric/fabric_synchronizer_config > /dev/null 2>&1 &
diff --git a/xos/synchronizers/fabric/steps/sync_host.yaml b/xos/synchronizers/fabric/steps/sync_host.yaml
new file mode 100644
index 0000000..58bccba
--- /dev/null
+++ b/xos/synchronizers/fabric/steps/sync_host.yaml
@@ -0,0 +1,20 @@
+---
+- hosts: 127.0.0.1
+ connection: local
+ vars:
+ rest_hostname: {{ rest_hostname }}
+ rest_port: {{ rest_port }}
+ rest_endpoint: {{ rest_endpoint }}
+ rest_json: '{{ rest_json }}'
+
+ tasks:
+ - debug: var=rest_json
+
+ - name: Call Fabric REST API
+ uri:
+ url: http://{{ '{{' }} rest_hostname {{ '}}' }}:{{ '{{' }} rest_port {{ '}}' }}/{{ '{{' }} rest_endpoint {{ '}}' }} #http://localhost:8181/onos/v1/network/configuration/
+ body: "{{ '{{' }} rest_json {{ '}}' }}"
+ body_format: raw
+ method: POST
+ user: karaf
+ password: karaf
diff --git a/xos/synchronizers/fabric/steps/sync_vroutertenant.py b/xos/synchronizers/fabric/steps/sync_vroutertenant.py
new file mode 100644
index 0000000..fd77ca2
--- /dev/null
+++ b/xos/synchronizers/fabric/steps/sync_vroutertenant.py
@@ -0,0 +1,103 @@
+import os
+import base64
+from collections import defaultdict
+from django.db.models import F, Q
+from xos.config import Config
+from synchronizers.base.openstacksyncstep import OpenStackSyncStep
+from synchronizers.base.syncstep import *
+from core.models import Controller
+from core.models import Image, ControllerImages
+from xos.logger import observer_logger as logger
+from synchronizers.base.ansible import *
+from services.vrouter.models import VRouterTenant
+from services.onos.models import ONOSService
+from services.fabric.models import FabricService
+import json
+
+class SyncVRouterTenant(SyncStep):
+ provides=[VRouterTenant]
+ observes = VRouterTenant
+ requested_interval=30
+ playbook='sync_host.yaml'
+
+ def get_fabric_onos_service(self):
+ fos = None
+ fs = FabricService.get_service_objects().all()[0]
+ if fs.subscribed_tenants.exists():
+ app = fs.subscribed_tenants.all()[0]
+ if app.provider_service:
+ ps = app.provider_service
+ fos = ONOSService.get_service_objects().filter(id=ps.id)[0]
+ return fos
+
+ def get_node_tag(self, node, tagname):
+ tags = Tag.select_by_content_object(node).filter(name=tagname)
+ return tags[0].value
+
+ def fetch_pending(self, deleted):
+ fs = FabricService.get_service_objects().all()[0]
+ if not fs.autoconfig:
+ return None
+
+ if (not deleted):
+ objs = VRouterTenant.get_tenant_objects().filter(Q(lazy_blocked=False))
+ else:
+ objs = VRouterTenant.get_deleted_tenant_objects()
+
+ return objs
+
+ def map_sync_inputs(self, vroutertenant):
+
+ fos = self.get_fabric_onos_service()
+
+ name = None
+ instance = None
+ # VRouterTenant setup is kind of hacky right now, we'll
+ # need to revisit. The idea is:
+ # * Look up the instance corresponding to the address
+ # * Look up the node running the instance
+ # * Get the "location" tag, push to the fabric
+ #
+ # Do we have a vCPE subscriber_tenant?
+ if (vroutertenant.subscriber_tenant):
+ sub = vroutertenant.subscriber_tenant
+ if (sub.kind == 'vCPE'):
+ instance_id = sub.get_attribute("instance_id")
+ if instance_id:
+ instance = Instance.objects.filter(id=instance_id)[0]
+ name = str(sub)
+ else:
+ # Maybe the VRouterTenant is for an instance
+ instance_id = vroutertenant.get_attribute("tenant_for_instance_id")
+ if instance_id:
+ instance = Instance.objects.filter(id=instance_id)[0]
+ name = str(instance)
+
+ node = instance.node
+ location = self.get_node_tag(node, "location")
+
+ # Is it a POST or DELETE?
+
+ # Create JSON
+ data = {
+ "%s/-1"%vroutertenant.public_mac : {
+ "basic" : {
+ "ips" : [ vroutertenant.public_ip ],
+ "location" : location
+ }
+ }
+ }
+
+ rest_json = json.dumps(data, indent=4)
+
+ fields = {
+ 'rest_hostname': fos.rest_hostname,
+ 'rest_port': fos.rest_port,
+ 'rest_json': rest_json,
+ 'rest_endpoint': "onos/v1/network/configuration/hosts",
+ 'ansible_tag': '%s'%name, # name of ansible playbook
+ }
+ return fields
+
+ def map_sync_outputs(self, controller_image, res):
+ pass
diff --git a/xos/synchronizers/fabric/stop.sh b/xos/synchronizers/fabric/stop.sh
new file mode 100755
index 0000000..d35b057
--- /dev/null
+++ b/xos/synchronizers/fabric/stop.sh
@@ -0,0 +1 @@
+pkill -9 -f fabric-synchronizer.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/services/exampleservice/__init__.py b/xos/synchronizers/vpgwc/__init__.py
old mode 100644
new mode 100755
similarity index 100%
rename from xos/services/exampleservice/__init__.py
rename to xos/synchronizers/vpgwc/__init__.py
diff --git a/xos/synchronizers/exampleservice/model-deps b/xos/synchronizers/vpgwc/model-deps
old mode 100644
new mode 100755
similarity index 100%
copy from xos/synchronizers/exampleservice/model-deps
copy to xos/synchronizers/vpgwc/model-deps
diff --git a/xos/synchronizers/vpgwc/run.sh b/xos/synchronizers/vpgwc/run.sh
new file mode 100755
index 0000000..821e149
--- /dev/null
+++ b/xos/synchronizers/vpgwc/run.sh
@@ -0,0 +1,3 @@
+# Runs the XOS observer using helloworldservice_config
+export XOS_DIR=/opt/xos
+python vpgwc-synchronizer.py -C $XOS_DIR/synchronizers/vpgwc/vpgwc_config
diff --git a/xos/synchronizers/vpgwc/steps/sync_vpgwc.py b/xos/synchronizers/vpgwc/steps/sync_vpgwc.py
new file mode 100644
index 0000000..446a521
--- /dev/null
+++ b/xos/synchronizers/vpgwc/steps/sync_vpgwc.py
@@ -0,0 +1,37 @@
+import os
+import sys
+from django.db.models import Q, F
+from services.mcord.models import MCORDService, VPGWCComponent
+from synchronizers.base.SyncInstanceUsingAnsible import SyncInstanceUsingAnsible
+
+parentdir = os.path.join(os.path.dirname(__file__), "..")
+sys.path.insert(0, parentdir)
+
+class SyncVPGWCComponent(SyncInstanceUsingAnsible):
+
+ provides = [VPGWCComponent]
+
+ observes = VPGWCComponent
+
+ requested_interval = 0
+
+ template_name = "sync_vpgwc.yaml"
+
+ service_key_name = "/opt/xos/configurations/mcord/mcord_private_key"
+
+ def __init__(self, *args, **kwargs):
+ super(SyncVPGWCComponent, self).__init__(*args, **kwargs)
+
+ def fetch_pending(self, deleted):
+
+ if (not deleted):
+ objs = VPGWCComponent.get_tenant_objects().filter(
+ Q(enacted__lt=F('updated')) | Q(enacted=None), Q(lazy_blocked=False))
+ else:
+
+ objs = VPGWCComponent.get_deleted_tenant_objects()
+
+ return objs
+
+ def get_extra_attributes(self, o):
+ return {"display_message": o.display_message, "s5s8_pgw_tag": o.s5s8_pgw_tag}
diff --git a/xos/synchronizers/vpgwc/steps/sync_vpgwc.yaml b/xos/synchronizers/vpgwc/steps/sync_vpgwc.yaml
new file mode 100644
index 0000000..a793976
--- /dev/null
+++ b/xos/synchronizers/vpgwc/steps/sync_vpgwc.yaml
@@ -0,0 +1,13 @@
+---
+- hosts: {{ instance_name }}
+ gather_facts: False
+ connection: ssh
+ user: ubuntu
+ sudo: yes
+ tasks:
+
+ - name: write message
+ shell: echo "{{ display_message }}" > /var/tmp/index.html
+
+ - name: setup s5s8_pgw interface config
+ shell: ./start_3gpp_int.sh eth1 {{ s5s8_pgw_tag }} {{ s5s8_pgw_ip }}/24
diff --git a/xos/synchronizers/vpgwc/stop.sh b/xos/synchronizers/vpgwc/stop.sh
new file mode 100755
index 0000000..299641a
--- /dev/null
+++ b/xos/synchronizers/vpgwc/stop.sh
@@ -0,0 +1,2 @@
+# Kill the observer
+pkill -9 -f vpgwc-synchronizer.py
diff --git a/xos/synchronizers/vpgwc/vpgwc-synchronizer.py b/xos/synchronizers/vpgwc/vpgwc-synchronizer.py
new file mode 100755
index 0000000..95f4081
--- /dev/null
+++ b/xos/synchronizers/vpgwc/vpgwc-synchronizer.py
@@ -0,0 +1,13 @@
+#!/usr/bin/env python
+
+# This imports and runs ../../xos-observer.py
+# Runs the standard XOS observer
+
+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/vpgwc/vpgwc_config b/xos/synchronizers/vpgwc/vpgwc_config
new file mode 100755
index 0000000..c6b9c23
--- /dev/null
+++ b/xos/synchronizers/vpgwc/vpgwc_config
@@ -0,0 +1,40 @@
+# Required by XOS
+[db]
+name=xos
+user=postgres
+password=password
+host=localhost
+port=5432
+
+# Required by XOS
+[api]
+nova_enabled=True
+
+# Sets options for the observer
+[observer]
+# Optional name
+name=vpgwc
+# This is the location to the dependency graph you generate
+dependency_graph=/opt/xos/synchronizers/vpgwc/model-deps
+# The location of your SyncSteps
+steps_dir=/opt/xos/synchronizers/vpgwc/steps
+# A temporary directory that will be used by ansible
+sys_dir=/opt/xos/synchronizers/vpgwc/sys
+# Location of the file to save logging messages to the backend log is often used
+logfile=/var/log/xos_backend.log
+# If this option is true, then nothing will change, we simply pretend to run
+pretend=False
+# If this is False then XOS will use an exponential backoff when the observer
+# fails, since we will be waiting for an instance, we don't want this.
+backoff_disabled=True
+# We want the output from ansible to be logged
+save_ansible_output=True
+# This determines how we SSH to a client, if this is set to True then we try
+# to ssh using the instance name as a proxy, if this is disabled we ssh using
+# the NAT IP of the instance. On CloudLab the first option will fail so we must
+# set this to False
+proxy_ssh=True
+proxy_ssh_key=/root/setup/id_rsa
+proxy_ssh_user=root
+[networking]
+use_vtn=True
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/tools/xos-manage b/xos/tools/xos-manage
index a4705d9..fcd14e1 100755
--- a/xos/tools/xos-manage
+++ b/xos/tools/xos-manage
@@ -152,6 +152,14 @@
python ./manage.py makemigrations vtn
python ./manage.py makemigrations fabric
#python ./manage.py makemigrations servcomp
+
+ if [[ -e /opt/xos/xos/xosbuilder_migration_list ]]; then
+ cat /opt/xos/xos/xosbuilder_migration_list | while read line; do
+ if [[ ! -z "$line" ]]; then
+ python ./manage.py makemigrations $line
+ fi
+ done
+ fi
}
function remigrate {
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..9e6cb41 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,72 @@
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
+ tosca_resource:
+ type: string
+ required: false
+ description: url of tosca resource
+ 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 +1137,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..0888c53 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,102 @@
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
+ tosca_resource:
+ type: string
+ required: false
+ description: url of tosca resource
+ 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 +1044,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 +2021,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/servicecontroller.py b/xos/tosca/resources/servicecontroller.py
new file mode 100644
index 0000000..d821b56
--- /dev/null
+++ b/xos/tosca/resources/servicecontroller.py
@@ -0,0 +1,50 @@
+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):
+ values = self.get_property(kind)
+ if values:
+ for i,value in enumerate(values.split(",")):
+ value = value.strip()
+
+ name=kind
+ if i>0:
+ name = "%s_%d" %( name, i)
+
+ scr = ServiceControllerResource.objects.filter(service_controller=obj, name=name, 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=name, 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, "tosca_resource", "python")
+ 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/vpgwccomponent.py b/xos/tosca/resources/vpgwccomponent.py
new file mode 100644
index 0000000..3b87111
--- /dev/null
+++ b/xos/tosca/resources/vpgwccomponent.py
@@ -0,0 +1,40 @@
+import os
+import pdb
+import sys
+import tempfile
+sys.path.append("/opt/tosca")
+from translator.toscalib.tosca_template import ToscaTemplate
+import pdb
+
+from services.mcord.models import VPGWCComponent, MCORDService
+
+from xosresource import XOSResource
+
+class XOSVPGWCComponent(XOSResource):
+ provides = "tosca.nodes.VPGWCComponent"
+ xos_model = VPGWCComponent
+ copyin_props = ["s5s8_pgw_tag", "display_message"]
+ name_field = None
+
+ def get_xos_args(self, throw_exception=True):
+ args = super(XOSVPGWCComponent, self).get_xos_args()
+
+ provider_name = self.get_requirement("tosca.relationships.MemberOfService", throw_exception=throw_exception)
+ if provider_name:
+ args["provider_service"] = self.get_xos_object(MCORDService, throw_exception=throw_exception, name=provider_name)
+
+ return args
+
+ def get_existing_objs(self):
+ args = self.get_xos_args(throw_exception=False)
+ provider_service = args.get("provider", None)
+ if provider_service:
+ return [ self.get_xos_object(provider_service=provider_service) ]
+ return []
+
+ def postprocess(self, obj):
+ pass
+
+ def can_delete(self, obj):
+ return super(XOSVPGWCComponent, self).can_delete(obj)
+
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)