Merged XOS master
diff --git a/Dockerfile b/Dockerfile
index 5d945a9..b69b7fd 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,4 @@
-FROM ubuntu:14.04.2
+FROM ubuntu:14.04.3
MAINTAINER Andy Bavier <acb@cs.princeton.edu>
# XXX Workaround for docker bug:
diff --git a/containers/observer/Dockerfile b/containers/observer/Dockerfile
new file mode 100644
index 0000000..7ec6592
--- /dev/null
+++ b/containers/observer/Dockerfile
@@ -0,0 +1,44 @@
+FROM xos
+
+# Install custom Ansible
+RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y \
+ openssh-client \
+ python-crypto \
+ python-jinja2 \
+ python-paramiko \
+ python-yaml \
+ python-httplib2 \
+ supervisor
+
+RUN \
+ git clone -b release1.8.2 git://github.com/ansible/ansible.git /opt/ansible && \
+ git clone -b release1.8.2 git://github.com/ansible/ansible-modules-extras.git /opt/ansible/lib/ansible/modules/extras && \
+ git clone -b release1.8.2 git://github.com/ansible/ansible-modules-extras.git /opt/ansible/v2/ansible/modules/extras && \
+ git clone git://github.com/sb98052/ansible-modules-core.git /opt/ansible/lib/ansible/modules/core && \
+ git clone git://github.com/sb98052/ansible-modules-core.git /opt/ansible/v2/ansible/modules/core && \
+ # git clone uses cached copy, doesn't pick up latest
+ git -C /opt/ansible pull && \
+ git -C /opt/ansible/lib/ansible/modules/core pull && \
+ git -C /opt/ansible/v2/ansible/modules/core pull
+
+
+# For Observer
+RUN mkdir -p /usr/local/share /bin /etc/ansible
+
+RUN cp /tmp/xos/containers/observer/conf/ansible-hosts /etc/ansible/hosts
+
+ADD http://phantomjs.googlecode.com/files/phantomjs-1.7.0-linux-x86_64.tar.bz2 /usr/local/share/
+
+RUN git clone git://git.planet-lab.org/fofum.git /tmp/fofum && \
+ cd /tmp/fofum; python setup.py install && \
+ rm -rf /tmp/fofum && \
+ tar jxvf /usr/local/share/phantomjs-1.7.0-linux-x86_64.tar.bz2 -C /usr/local/share/ && \
+ rm -f /usr/local/share/phantomjs-1.7.0-linux-x86_64.tar.bz2 && \
+ ln -s /usr/local/share/phantomjs-1.7.0-linux-x86_64 /usr/local/share/phantomjs && \
+ ln -s /usr/local/share/phantomjs/bin/phantomjs /bin/phantomjs
+
+
+# Supervisor
+RUN cp /tmp/xos/containers/observer/conf/observer.conf /etc/supervisor/conf.d/
+
+CMD /usr/bin/supervisord -c /etc/supervisor/conf.d/observer.conf
diff --git a/containers/observer/Makefile b/containers/observer/Makefile
new file mode 100644
index 0000000..e7fedf5
--- /dev/null
+++ b/containers/observer/Makefile
@@ -0,0 +1,13 @@
+CONTAINER_NAME:=observer-server
+
+.PHONY: build
+build: ; docker build --rm -t observer .
+
+.PHONY: run
+run: ; docker run -d --name ${CONTAINER_NAME} observer
+
+.PHONY: stop
+stop: ; docker stop ${CONTAINER_NAME}
+
+.PHONY: rm
+rm: ; docker rm ${CONTAINER_NAME}
diff --git a/xos/configurations/opencloud/ansible-hosts b/containers/observer/conf/ansible-hosts
similarity index 100%
rename from xos/configurations/opencloud/ansible-hosts
rename to containers/observer/conf/ansible-hosts
diff --git a/containers/observer/conf/observer.conf b/containers/observer/conf/observer.conf
new file mode 100644
index 0000000..48f61dd
--- /dev/null
+++ b/containers/observer/conf/observer.conf
@@ -0,0 +1,9 @@
+[supervisord]
+logfile=/var/log/supervisord.log ; (main log file;default $CWD/supervisord.log)
+pidfile=/var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
+nodaemon=true
+
+[program:observer]
+command=python /opt/xos/xos-observer.py
+stderr_logfile=/var/log/supervisor/observer.err.log
+stdout_logfile=/var/log/supervisor/observer.out.log
diff --git a/containers/postgresql/Dockerfile b/containers/postgresql/Dockerfile
new file mode 100644
index 0000000..4d4ebfd
--- /dev/null
+++ b/containers/postgresql/Dockerfile
@@ -0,0 +1,35 @@
+FROM ubuntu
+
+RUN apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys B97B0AFCAA1A47F044F244A07FCC7D46ACCC4CF8
+
+RUN echo "deb http://apt.postgresql.org/pub/repos/apt/ precise-pgdg main" > /etc/apt/sources.list.d/pgdg.list
+
+RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y --force-yes\
+ python-software-properties \
+ software-properties-common \
+ postgresql-9.3 \
+ postgresql-client-9.3 \
+ postgresql-contrib-9.3
+
+# Workaround for AUFS issue
+# https://github.com/docker/docker/issues/783#issuecomment-56013588
+RUN mkdir /etc/ssl/private-copy; mv /etc/ssl/private/* /etc/ssl/private-copy/; rm -r /etc/ssl/private; mv /etc/ssl/private-copy /etc/ssl/private; chmod -R 0700 /etc/ssl/private; chown -R postgres /etc/ssl/private
+
+USER postgres
+
+RUN /etc/init.d/postgresql start && \
+ psql --command "ALTER USER postgres WITH SUPERUSER PASSWORD 'password' " && \
+ psql --command "CREATE DATABASE xos"
+
+# Allow remote connections.
+RUN echo "host all all 0.0.0.0/0 md5" >> /etc/postgresql/9.3/main/pg_hba.conf
+RUN echo "host all all 0.0.0.0/0 password" >> /etc/postgresql/9.3/main/pg_hba.conf
+
+RUN echo "listen_addresses='*'" >> /etc/postgresql/9.3/main/postgresql.conf
+
+# Expose the PostgreSQL port
+EXPOSE 5432
+
+VOLUME ["/etc/postgresql", "/var/log/postgresql", "/var/lib/postgresql"]
+
+CMD ["/usr/lib/postgresql/9.3/bin/postgres", "-D", "/var/lib/postgresql/9.3/main", "-c", "config_file=/etc/postgresql/9.3/main/postgresql.conf"]
diff --git a/containers/postgresql/Makefile b/containers/postgresql/Makefile
new file mode 100644
index 0000000..327f661
--- /dev/null
+++ b/containers/postgresql/Makefile
@@ -0,0 +1,21 @@
+.PHONY: build
+build: ; docker build --rm -t postgres .
+
+.PHONY: run
+run: ; docker run -d -p 5432:5432 --name postgres-server postgres
+
+.PHONY: stop
+stop: ; docker stop postgres-server
+
+.PHONY: rm
+rm: ; docker rm postgres-server
+
+.PHONE: rmi
+rmi: ; docker rmi postgres
+
+.PHONY: backup
+backupvol: ; docker run --volumes-from postgres-server -v /backup:/backup postgres tar cvf /backup/backup-postgres.tar /var/lib/postgresql
+
+.PHONY: restore
+restorevol: ; docker run --volumes-from postgres-server -v /backup:/backup postgres cd /var/lib/postgresql && tar xvf /backup/backup-postgres.tar
+
diff --git a/containers/xos/Dockerfile b/containers/xos/Dockerfile
new file mode 100644
index 0000000..37bd55b
--- /dev/null
+++ b/containers/xos/Dockerfile
@@ -0,0 +1,88 @@
+FROM ubuntu:14.04.3
+
+# XXX Workaround for docker bug:
+# https://github.com/docker/docker/issues/6345
+# Kernel 3.15 breaks docker, uss the line below as a workaround
+# until there is a fix
+RUN ln -s -f /bin/true /usr/bin/chfn
+# XXX End workaround
+
+# Install.
+RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y \
+ curl \
+ gcc \
+ geoip-database \
+ git \
+ graphviz \
+ graphviz-dev \
+ libgeoip1 \
+ libxslt1.1 \
+ libxslt1-dev \
+ libyaml-dev \
+ m4 \
+ pkg-config \
+ python-dev \
+ python-httplib2 \
+ python-pip \
+ python-psycopg2 \
+ python-pycurl \
+ python-setuptools \
+ tar \
+ wget \
+##### observer dependencies
+ python-keystoneclient \
+ python-novaclient \
+ python-neutronclient \
+ python-glanceclient \
+ python-ceilometerclient
+
+RUN pip install -U \
+ django==1.7 \
+ django-bitfield \
+ django-crispy-forms \
+ django-encrypted-fields \
+ django_evolution \
+ django-extensions \
+ django-filter \
+ django-geoposition \
+ django-ipware \
+ django_rest_swagger \
+ django-suit \
+ django-timezones \
+ djangorestframework==2.4.4 \
+ dnslib \
+ google_api_python_client \
+ httplib2 \
+ httplib2.ca_certs_locater \
+ lxml \
+ markdown \
+ netaddr \
+ python-dateutil \
+ python_gflags \
+ python-keyczar \
+ pygraphviz \
+ pytz \
+ pyyaml \
+ requests
+
+ADD http://code.jquery.com/jquery-1.9.1.min.js /usr/local/lib/python2.7/dist-packages/suit/static/suit/js/
+
+# Install XOS
+RUN git clone git://github.com/open-cloud/xos.git /tmp/xos && \
+ mv /tmp/xos/xos /opt/ && \
+ chmod +x /opt/xos/scripts/opencloud && \
+ /opt/xos/scripts/opencloud genkeys
+
+# install Tosca engine
+RUN bash /opt/xos/tosca/install_tosca.sh
+
+EXPOSE 8000
+
+# Set environment variables.
+ENV HOME /root
+
+# Define working directory.
+WORKDIR /root
+
+# Define default command.
+CMD python /opt/xos/manage.py runserver 0.0.0.0:8000 --insecure
diff --git a/containers/xos/Makefile b/containers/xos/Makefile
new file mode 100644
index 0000000..c71873e
--- /dev/null
+++ b/containers/xos/Makefile
@@ -0,0 +1,17 @@
+CONTAINER_NAME:=xos-server
+TOSCA_CONFIG_PATH:=/opt/xos/configurations/opencloud/opencloud.yaml
+
+.PHONY: build
+build: ; docker build --rm -t xos . && ./initdb
+
+.PHONY: run
+run: ; docker run -d --name ${CONTAINER_NAME} -p 80:8000 xos
+
+.PHONY: runtosca
+runtosca: ; docker exec -it ${CONTAINER_NAME} /usr/bin/python /opt/xos/tosca/run.py padmin@vicci.org ${TOSCA_CONFIG_PATH}
+
+.PHONY: stop
+stop: ; docker stop ${CONTAINER_NAME}
+
+.PHONY: rm
+rm: ; docker rm ${CONTAINER_NAME}
diff --git a/containers/xos/initdb b/containers/xos/initdb
new file mode 100755
index 0000000..bd020c5
--- /dev/null
+++ b/containers/xos/initdb
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+IMAGE_NAME=xos
+DB_HOST=$(wget http://ipinfo.io/ip -qO -)
+
+# configure db host
+docker run -it $IMAGE_NAME sed -i '0,/host/{s/host=localhost/host='$DB_HOST'/}' /opt/xos/xos_config
+CONTAINER_ID=$(docker ps -a | grep $IMAGE_NAME | head -1 | awk '{print $1}')
+echo $CONTAINER_ID $IMAGE_NAME
+docker commit $CONTAINER_ID $IMAGE_NAME
+
+# init db schema
+docker run -it $IMAGE_NAME /opt/xos/scripts/opencloud makemigrations
+CONTAINER_ID=$(docker ps -a | grep $IMAGE_NAME | head -1 | awk '{print $1}')
+# run overrides the CMD specifed in the Dockerfile, so we re-set the CMD in the final commit"
+docker commit --change "CMD python /opt/xos/manage.py runserver 0.0.0.0:8000 --insecure" $CONTAINER_ID $IMAGE_NAME
diff --git a/docker-cp.sh b/docker-cp.sh
index 280a8d9..bec511d 100755
--- a/docker-cp.sh
+++ b/docker-cp.sh
@@ -5,4 +5,5 @@
XOS=$( docker ps|grep "xos"|awk '{print $NF}' )
FOLDER=`docker inspect -f '{{.Id}}' $XOS`
-cp $1 /var/lib/docker/aufs/mnt/$FOLDER/$2
\ No newline at end of file
+#cp $1 /var/lib/docker/aufs/mnt/$FOLDER/$2
+docker cp $1 $XOS:$2
diff --git a/xos/apigen/hpc-api.template.py b/xos/apigen/hpc-api.template.py
index 291403a..301346b 100644
--- a/xos/apigen/hpc-api.template.py
+++ b/xos/apigen/hpc-api.template.py
@@ -37,7 +37,7 @@
def get_hpc_REST_patterns():
return patterns('',
url(r'^hpcapi/$', hpc_api_root),
- {% for object in generator.all %}
+ {% for object in generator.rest_models %}
url(r'hpcapi/{{ object.rest_name }}/$', {{ object.camel }}List.as_view(), name='{{ object.singular }}-list'),
url(r'hpcapi/{{ object.rest_name }}/(?P<pk>[a-zA-Z0-9\-]+)/$', {{ object.camel }}Detail.as_view(), name ='{{ object.singular }}-detail'),
{% endfor %}
@@ -46,7 +46,7 @@
@api_view(['GET'])
def hpc_api_root(request, format=None):
return Response({
- {% for object in generator.all %}'{{ object.plural }}': reverse('{{ object }}-list', request=request, format=format),
+ {% for object in generator.rest_models %}'{{ object.plural }}': reverse('{{ object }}-list', request=request, format=format),
{% endfor %}
})
@@ -104,7 +104,7 @@
newModel = through(**{local_fieldName: obj, remote_fieldName: item})
newModel.save()
-{% for object in generator.all %}
+{% for object in generator.rest_models %}
class {{ object.camel }}Serializer(serializers.HyperlinkedModelSerializer):
id = IdField()
@@ -154,14 +154,14 @@
{% endfor %}
serializerLookUp = {
-{% for object in generator.all %}
+{% for object in generator.rest_models %}
{{ object.camel }}: {{ object.camel }}Serializer,
{% endfor %}
None: None,
}
# Based on core/views/*.py
-{% for object in generator.all %}
+{% for object in generator.rest_models %}
class {{ object.camel }}List(XOSListCreateAPIView):
queryset = {{ object.camel }}.objects.select_related().all()
diff --git a/xos/apigen/list.txt b/xos/apigen/list.txt
new file mode 100644
index 0000000..3e115e3
--- /dev/null
+++ b/xos/apigen/list.txt
@@ -0,0 +1,3 @@
+{% for o in generator.all %}
+{{ o.camel }}
+{% endfor %}
diff --git a/xos/apigen/modelgen b/xos/apigen/modelgen
index 7f740d1..63cf5b7 100644
--- a/xos/apigen/modelgen
+++ b/xos/apigen/modelgen
@@ -7,8 +7,7 @@
import json
import re
from django.template import Context, Template
-
-blacklist = ['SingletonModel','PlCoreBase']
+from optparse import OptionParser
# Django set up
@@ -16,6 +15,8 @@
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "xos.settings")
from django.db.models.fields.related import ForeignKey, ManyToManyField
+options = None
+
def singular(foo, keys):
for k in keys:
if (foo==k+'es'):
@@ -40,7 +41,7 @@
for classname in dir(models_module):
c = getattr(models_module, classname, None)
- if type(c)==type(PlCoreBase) and c.__name__ not in blacklist:
+ if type(c)==type(PlCoreBase) and c.__name__ not in options.blacklist:
model_classes.append(c)
return model_classes
@@ -90,6 +91,10 @@
class Generator(dict):
def all(self):
return self.values()
+
+ def rest_models(self):
+ norest = [x.lower() for x in options.norest]
+ return [v for v in self.values() if not (str(v) in norest)]
def regex(self, r):
filtered = filter(lambda o:re.match(r,str(o)), self.values())
@@ -122,6 +127,10 @@
cobj.multi = True
cobj.plural_name = related_name
refobj.refs.append(cobj)
+ elif f.name.endswith("_ptr"):
+ # django inherited model, for example HPCService
+ # cause swagger and REST to break
+ pass
else:
obj.props.append(f.name)
@@ -144,9 +153,9 @@
if (related_name.endswith("+")):
continue
- if (related_name!='+' and related_name.lower()!=str(obj).lower()):
- #print "XXX2", obj, f, related_name, related_model_name, refobj.plural_name
+ if (related_name!='+') and related_model_name in self: # and related_name.lower()!=str(obj).lower()):
refobj = self[related_model_name]
+ #print "XXX2", obj, f, related_name, related_model_name, refobj.plural_name
cobj = copy.deepcopy(refobj)
cobj.multi = True
@@ -154,22 +163,32 @@
-
+
def main():
- if len(sys.argv)==3:
- apps = [x.strip() for x in sys.argv[1].split(",")]
- output = sys.argv[2]
- elif len(sys.argv)==2:
- apps = ["core"]
- output = sys.argv[1]
- else:
- print 'Usage: modelgen <output_template>'
- print 'Alternative Usage: modelgen <app> <output_template>'
- exit(1)
+ global options
+ parser = OptionParser(usage="modelgen [options] <template_fn>", )
+
+ parser.add_option("-a", "--app", dest="apps",
+ help="list of applications to parse", metavar="APP", default=[], action="append")
+ parser.add_option("-b", "--blacklist", dest="blacklist",
+ help="add model name to blacklist", metavar="MODEL", default=["SingletonModel", "PlCoreBase"], action="append")
+ parser.add_option("-n", "--no-rest", dest="norest",
+ help="do not generate rest api for model", metavar="MODEL", default=["SingletonModel", "PlCoreBase"], action="append")
+
+ (options, args) = parser.parse_args(sys.argv[1:])
+
+ if not options.apps:
+ options.apps = ["core"]
+
+ if len(args)!=1:
+ print 'Usage: modelgen [options] <template_fn>'
+ exit(1)
+
+ output = args[0]
generator = Generator()
- models = enum_classes(apps)
+ models = enum_classes(options.apps)
for m in models:
generator.add_object(m)
diff --git a/xos/ceilometer/models.py b/xos/ceilometer/models.py
index fbfecd3..a838c4e 100644
--- a/xos/ceilometer/models.py
+++ b/xos/ceilometer/models.py
@@ -41,12 +41,18 @@
def save(self, *args, **kwargs):
if not self.creator:
if not getattr(self, "caller", None):
- # caller must be set when creating a vCPE since it creates a slice
+ # caller must be set when creating a monitoring channel since it creates a slice
raise XOSProgrammingError("MonitoringChannel's self.caller was not set")
self.creator = self.caller
if not self.creator:
raise XOSProgrammingError("MonitoringChannel's self.creator was not set")
+ if self.pk is None:
+ #Allow only one monitoring channel per user
+ channel_count = sum ( [1 for channel in MonitoringChannel.objects.filter(kind=CEILOMETER_KIND) if (channel.creator == self.creator)] )
+ if channel_count > 0:
+ raise XOSValidationError("Already %s channels exist for user Can only create max 1 MonitoringChannel instance per user" % str(channel_count))
+
super(MonitoringChannel, self).save(*args, **kwargs)
model_policy_monitoring_channel(self.pk)
diff --git a/xos/configurations/bash/Dockerfile.bash b/xos/configurations/bash/Dockerfile.bash
index 2022392..a9c224d 100644
--- a/xos/configurations/bash/Dockerfile.bash
+++ b/xos/configurations/bash/Dockerfile.bash
@@ -1,8 +1,12 @@
RUN mkdir -p /root/setup
ADD xos/configurations/common/admin-openrc.sh /root/setup/
+ADD xos/configurations/common/controller_settings /root/setup/
ADD xos/configurations/common/flat_net_name /root/setup/
ADD xos/configurations/common/cloudlab-nodes.yaml /opt/xos/configurations/commmon/
ADD xos/configurations/common/id_rsa.pub /root/setup/padmin_public_key
+ADD xos/configurations/common/node_key.pub /root/setup/node_key.pub
+ADD xos/configurations/common/node_key /root/setup/node_key
+ADD xos/configurations/common/ceilometer_url /root/setup/ceilometer_url
CMD /usr/bin/make -C /opt/xos/configurations/bash -f Makefile.inside; /bin/bash
diff --git a/xos/configurations/common/Makefile.cloudlab b/xos/configurations/common/Makefile.cloudlab
index 5712765..43e7497 100644
--- a/xos/configurations/common/Makefile.cloudlab
+++ b/xos/configurations/common/Makefile.cloudlab
@@ -1,10 +1,15 @@
-all: prereqs admin-openrc flat_name nodes_yaml public_key private_key
+MYFLATLANIF:=$(shell netstat -i |grep "flat"|awk '{print $$1}' )
+MYFLATLANIP:=$(shell ifconfig $(MYFLATLANIF) | grep "inet addr" | awk -F: '{print $$2}' | awk '{print $$1}' )
+
+all: prereqs admin-openrc flat_name nodes_yaml public_key private_key ceilometer_url node_key
prereqs:
make -f Makefile.prereqs
admin-openrc:
sudo cat /root/setup/admin-openrc.sh > admin-openrc.sh
+ sudo cat /root/setup/settings > controller_settings
+ echo 'CONTROLLER_FLAT_LAN_IP=$(MYFLATLANIP)' >> controller_settings
flat_name:
sudo bash -c "source /root/setup/admin-openrc.sh ; neutron net-list" |grep flat|awk '{printf "%s",$$4}' > flat_net_name
@@ -12,6 +17,9 @@
nodes_yaml:
bash ./make-cloudlab-nodes-yaml.sh
+ceilometer_url:
+ echo http://`hostname -i`/xosmetering/ > ceilometer_url
+
public_key: ~/.ssh/id_rsa.pub
cp ~/.ssh/id_rsa.pub .
@@ -20,3 +28,7 @@
~/.ssh/id_rsa.pub:
cat /dev/zero | ssh-keygen -q -N ""
+
+node_key:
+ sudo cat /root/setup/id_rsa > node_key
+ sudo cat /root/setup/id_rsa.pub > node_key.pub
diff --git a/xos/configurations/common/admin-openrc.sh b/xos/configurations/common/admin-openrc.sh
deleted file mode 100644
index e69de29..0000000
--- a/xos/configurations/common/admin-openrc.sh
+++ /dev/null
diff --git a/xos/configurations/common/cloudlab.yaml b/xos/configurations/common/cloudlab.yaml
index 807d931..a0beeeb 100644
--- a/xos/configurations/common/cloudlab.yaml
+++ b/xos/configurations/common/cloudlab.yaml
@@ -42,9 +42,13 @@
admin_user: { get_script_env: [ SELF, adminrc, OS_USERNAME, LOCAL_FILE] }
admin_password: { get_script_env: [ SELF, adminrc, OS_PASSWORD, LOCAL_FILE] }
admin_tenant: { get_script_env: [ SELF, adminrc, OS_TENANT_NAME, LOCAL_FILE] }
+ rabbit_user: { get_script_env: [ SELF, controller_settings, RABBIT_USER, LOCAL_FILE] }
+ rabbit_password: { get_script_env: [ SELF, controller_settings, RABBIT_PASS, LOCAL_FILE] }
+ rabbit_host: { get_script_env: [ SELF, controller_settings, CONTROLLER_FLAT_LAN_IP, LOCAL_FILE] }
domain: Default
artifacts:
adminrc: /root/setup/admin-openrc.sh
+ controller_settings: /root/setup/controller_settings
mysite:
type: tosca.nodes.Site
diff --git a/xos/configurations/cord/Dockerfile.cord b/xos/configurations/cord/Dockerfile.cord
index a21c7d0..f7fdb65 100644
--- a/xos/configurations/cord/Dockerfile.cord
+++ b/xos/configurations/cord/Dockerfile.cord
@@ -1,16 +1,24 @@
RUN mkdir -p /root/setup
ADD xos/configurations/common/admin-openrc.sh /root/setup/
+ADD xos/configurations/common/controller_settings /root/setup/
ADD xos/configurations/common/flat_net_name /root/setup/
ADD xos/configurations/common/cloudlab-nodes.yaml /opt/xos/configurations/commmon/
ADD xos/configurations/common/id_rsa.pub /root/setup/padmin_public_key
ADD xos/configurations/common/id_rsa.pub /opt/xos/observers/vcpe/vcpe_public_key
ADD xos/configurations/common/id_rsa /opt/xos/observers/vcpe/vcpe_private_key
+ADD xos/configurations/common/id_rsa.pub /opt/xos/observers/monitoring_channel/monitoring_channel_public_key
+ADD xos/configurations/common/id_rsa /opt/xos/observers/monitoring_channel/monitoring_channel_private_key
ADD xos/configurations/common/id_rsa.pub /opt/xos/observers/onos/onos_key.pub
ADD xos/configurations/common/id_rsa /opt/xos/observers/onos/onos_key
+ADD xos/configurations/common/node_key.pub /root/setup/node_key.pub
+ADD xos/configurations/common/node_key /root/setup/node_key
+ADD xos/configurations/common/ceilometer_url /root/setup/ceilometer_url
ADD xos/observers/vcpe/supervisor/vcpe-observer.conf /etc/supervisor/conf.d/
ADD xos/observers/vbng/supervisor/vbng-observer.conf /etc/supervisor/conf.d/
ADD xos/observers/onos/supervisor/onos-observer.conf /etc/supervisor/conf.d/
+ADD xos/observers/monitoring_channel/supervisor/monitoring_channel_observer.conf /etc/supervisor/conf.d/
RUN sed -i 's/proxy_ssh=True/proxy_ssh=False/' /opt/xos/observers/vcpe/vcpe_observer_config
+RUN sed -i 's/proxy_ssh=True/proxy_ssh=False/' /opt/xos/observers/monitoring_channel/monitoring_channel_observer_config
CMD /usr/bin/make -C /opt/xos/configurations/cord -f Makefile.inside; /bin/bash
diff --git a/xos/configurations/cord/Makefile b/xos/configurations/cord/Makefile
index 40ff5a1..4c2e423 100644
--- a/xos/configurations/cord/Makefile
+++ b/xos/configurations/cord/Makefile
@@ -2,7 +2,7 @@
RUNNING_CONTAINER:=$(shell sudo docker ps|grep "xos"|awk '{print $$NF}')
LAST_CONTAINER=$(shell sudo docker ps -l -q)
-test: common_cloudlab
+test: common_cloudlab ceilometer_dashboard
echo "# Autogenerated -- do not edit" > Dockerfile
cat ../common/Dockerfile.common Dockerfile.cord >> Dockerfile
cd ../../..; sudo docker build -t xos -f xos/configurations/cord/Dockerfile .
@@ -12,6 +12,12 @@
common_cloudlab:
make -C ../common -f Makefile.cloudlab
+ceilometer_dashboard:
+ #NOTE: The below dashboard install scripts assume
+ #clouldlab openstack environment created using "OpenStack" profile
+ bash install_xos_ceilometer_dashboard.sh
+ bash install_ceilometer_vcpe_notification_listener.sh
+
stop:
sudo docker stop $(RUNNING_CONTAINER)
diff --git a/xos/configurations/cord/Makefile.inside b/xos/configurations/cord/Makefile.inside
index a4bb5f1..c412f25 100644
--- a/xos/configurations/cord/Makefile.inside
+++ b/xos/configurations/cord/Makefile.inside
@@ -5,6 +5,7 @@
python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/cloudlab.yaml
python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/cloudlab-nodes.yaml
python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/cord/cord.yaml
+ python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/cord/ceilometer.yaml
run_develserver:
cd /opt/xos; python manage.py runserver 0.0.0.0:8000 --insecure
diff --git a/xos/configurations/cord/README.md b/xos/configurations/cord/README.md
index efabcb2..4d64953 100644
--- a/xos/configurations/cord/README.md
+++ b/xos/configurations/cord/README.md
@@ -17,11 +17,11 @@
and Open vSwitch (OvS) switches. At a high level the dataplane looks like this:
```
- olt virtualbng
- ---- ----
- ONOS ONOS
- | |
-client ----> OvS ----> vCPE ----> OvS ----> Internet
+ olt virtualbng
+ ---- ----
+ ONOS ONOS
+ | |
+client ----> CPqD ----> vCPE ----> OvS ----> Internet
1 2 3 4
```
diff --git a/xos/configurations/cord/ceilometer.yaml b/xos/configurations/cord/ceilometer.yaml
new file mode 100644
index 0000000..73c18db
--- /dev/null
+++ b/xos/configurations/cord/ceilometer.yaml
@@ -0,0 +1,99 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: Setup CORD-related services -- vOLT, vCPE, vBNG.
+
+imports:
+ - custom_types/xos.yaml
+
+node_types:
+ tosca.nodes.CeilometerTenant:
+ derived_from: tosca.nodes.Root
+ description: >
+ CORD: A Tenant of the Ceilometer Service.
+ properties:
+ kind:
+ type: string
+ default: generic
+ description: Kind of tenant
+
+topology_template:
+ node_templates:
+ service_ceilometer:
+ type: tosca.nodes.Service
+ requirements:
+ properties:
+ view_url: /admin/ceilometer/ceilometerservice/$id$/
+ kind: ceilometer
+# public_key: { get_artifact: [ SELF, pubkey, LOCAL_FILE] }
+# artifacts:
+# pubkey: /opt/xos/observers/vcpe/vcpe_public_key
+
+
+ Private:
+ type: tosca.nodes.NetworkTemplate
+
+ ceilometer_network:
+ type: tosca.nodes.network.Network.XOS
+ properties:
+ ip_version: 4
+ labels: ceilometer_client_access
+ requirements:
+ - network_template:
+ node: Private
+ relationship: tosca.relationships.UsesNetworkTemplate
+ - owner:
+ node: mysite_ceilometer
+ relationship: tosca.relationships.MemberOfSlice
+ - connection:
+ node: mysite_ceilometer
+ relationship: tosca.relationships.ConnectsToSlice
+
+ mysite:
+ type: tosca.nodes.Site
+
+ mysite_ceilometer:
+ description: Ceilometer Proxy Slice
+ type: tosca.nodes.Slice
+ requirements:
+ - ceilometer_service:
+ node: service_ceilometer
+ relationship: tosca.relationships.MemberOfService
+ - site:
+ node: mysite
+ relationship: tosca.relationships.MemberOfSite
+
+ my_ceilometer_tenant:
+ description: Ceilometer Service default Tenant
+ type: tosca.nodes.CeilometerTenant
+ requirements:
+ - provider_service:
+ node: service_ceilometer
+ relationship: tosca.relationships.MemberOfService
+
+ Ceilometer:
+ type: tosca.nodes.DashboardView
+ properties:
+ url: { get_artifact: [ SELF, ceilometer_url, LOCAL_FILE] }
+ artifacts:
+ ceilometer_url: /root/setup/ceilometer_url
+
+ Tenant:
+ type: tosca.nodes.DashboardView
+ properties:
+ no-create: true
+ no-update: true
+ no-delete: true
+
+ padmin@vicci.org:
+ type: tosca.nodes.User
+ properties:
+ firstname: XOS
+ lastname: admin
+ is_admin: true
+ requirements:
+ - tenant_dashboard:
+ node: Tenant
+ relationship: tosca.relationships.UsesDashboard
+ - ceilometer_dashboard:
+ node: Ceilometer
+ relationship: tosca.relationships.UsesDashboard
diff --git a/xos/configurations/cord/ceilometer_vcpe_notification_agent.tar.gz b/xos/configurations/cord/ceilometer_vcpe_notification_agent.tar.gz
new file mode 100644
index 0000000..dcc6765
--- /dev/null
+++ b/xos/configurations/cord/ceilometer_vcpe_notification_agent.tar.gz
Binary files differ
diff --git a/xos/configurations/cord/cord.yaml b/xos/configurations/cord/cord.yaml
index 9d850b2..e9a6291 100644
--- a/xos/configurations/cord/cord.yaml
+++ b/xos/configurations/cord/cord.yaml
@@ -40,7 +40,7 @@
# generate a URL from its IP address
# vbng_url: http://10.11.10.24:8181/onos/virtualbng/
- service_ONOS:
+ service_ONOS_vBNG:
type: tosca.nodes.ONOSService
requirements:
properties:
@@ -50,34 +50,46 @@
artifacts:
pubkey: /opt/xos/observers/onos/onos_key.pub
+#
+# To actually bring up the vBNG app
+# - Set up the dataplane using the ansible script
+# - Log into the vBNG ONOS and run 'devices' to get switch dpID
+# - Change the dpID values in vBNG ONOS app in XOS GUI
+# - (Synchronizer should copy the files to ONOS container immediately)
+# - Log into service_ONOS_vBNG VM and restart ONOS Docker container
+# (Should roll this step into a Synchronizer)
+#
vBNG_ONOS_app:
type: tosca.nodes.ONOSvBNGApp
requirements:
- onos_tenant:
- node: service_ONOS
+ node: service_ONOS_vBNG
relationship: tosca.relationships.TenantOfService
- vbng_service:
node: service_vbng
relationship: tosca.relationships.UsedByService
properties:
dependencies: org.onosproject.proxyarp, org.onosproject.virtualbng, org.onosproject.openflow, org.onosproject.fwd
- config_addresses.json: >
+ config_network-cfg.json: >
{
- "addresses" : [
- {
- "dpid" : "00:00:00:00:00:00:00:a1",
- "port" : "1",
- "ips" : [10.0.1.253/24"],
- "mac" : "00:00:00:00:00:99"
-
- },
- {
- "dpid" : "00:00:00:00:00:00:00:a5",
- "port" : "2",
- "ips" : ["10.254.0.1/24"],
- "mac" : "00:00:00:00:00:98"
- }
- ]
+ "ports" : {
+ "of:0000000000000001/1" : {
+ "interfaces" : [
+ {
+ "ips" : [ "10.0.1.253/24" ],
+ "mac" : "00:00:00:00:00:99"
+ }
+ ]
+ },
+ "of:0000000000000001/2" : {
+ "interfaces" : [
+ {
+ "ips" : [ "10.254.0.2/24" ],
+ "mac" : "00:00:00:00:00:98"
+ }
+ ]
+ }
+ }
}
config_virtualbng.json: >
{
@@ -87,9 +99,34 @@
"nextHopIpAddress" : "10.254.0.1",
"publicFacingMac" : "00:00:00:00:00:66",
"xosIpAddress" : "10.11.10.1",
- "xosRestPort" : "9999"
+ "xosRestPort" : "9999",
+ "hosts" : {
+ "cp-1.devel.xos-pg0.clemson.cloudlab.us" : "of:0000000000000001/1",
+ "cp-2.devel.xos-pg0.clemson.cloudlab.us" : "of:0000000000000001/1"
+ }
}
+ service_ONOS_vOLT:
+ type: tosca.nodes.ONOSService
+ requirements:
+ properties:
+ kind: onos
+ view_url: /admin/onos/onosservice/$id$/
+ public_key: { get_artifact: [ SELF, pubkey, LOCAL_FILE] }
+ artifacts:
+ pubkey: /opt/xos/observers/onos/onos_key.pub
+
+ vOLT_ONOS_app:
+ type: tosca.nodes.ONOSvOLTApp
+ requirements:
+ - onos_tenant:
+ node: service_ONOS_vOLT
+ relationship: tosca.relationships.TenantOfService
+ - volt_service:
+ node: service_volt
+ relationship: tosca.relationships.UsedByService
+ properties:
+ dependencies: org.onosproject.olt
# Network templates
Private:
@@ -189,12 +226,23 @@
node: mysite
relationship: tosca.relationships.MemberOfSite
- mysite_onos:
- description: ONOS Controller Slice
+ mysite_onos_vbng:
+ description: ONOS Controller Slice for vBNG
type: tosca.nodes.Slice
requirements:
- ONOS:
- node: service_ONOS
+ node: service_ONOS_vBNG
+ relationship: tosca.relationships.MemberOfService
+ - site:
+ node: mysite
+ relationship: tosca.relationships.MemberOfSite
+
+ mysite_onos_volt:
+ description: ONOS Controller Slice for vOLT
+ type: tosca.nodes.Slice
+ requirements:
+ - ONOS:
+ node: service_ONOS_vOLT
relationship: tosca.relationships.MemberOfService
- site:
node: mysite
@@ -217,7 +265,7 @@
relationship: tosca.relationships.MemberOfSite
mysite_clients:
- description: slice for clients at the subscriber
+ description: slice for clients at the subscriber
type: tosca.nodes.Slice
requirements:
- site:
@@ -245,7 +293,7 @@
version: 14.10
requirements:
- slice:
- node: mysite_onos
+ node: mysite_onos_vbng
relationship: tosca.relationships.MemberOfSlice
onos_app_2:
@@ -267,7 +315,7 @@
version: 14.10
requirements:
- slice:
- node: mysite_onos
+ node: mysite_onos_volt
relationship: tosca.relationships.MemberOfSlice
# VM for running the OVS controlled by vBNG
diff --git a/xos/configurations/cord/dataplane/ansible.cfg b/xos/configurations/cord/dataplane/ansible.cfg
new file mode 100644
index 0000000..9100590
--- /dev/null
+++ b/xos/configurations/cord/dataplane/ansible.cfg
@@ -0,0 +1,4 @@
+[defaults]
+remote_user = ubuntu
+private_key_file = ~/.ssh/id_rsa
+host_key_checking = false
\ No newline at end of file
diff --git a/xos/configurations/cord/dataplane/dataplane.yaml b/xos/configurations/cord/dataplane/dataplane.yaml
new file mode 100644
index 0000000..4799515
--- /dev/null
+++ b/xos/configurations/cord/dataplane/dataplane.yaml
@@ -0,0 +1,100 @@
+---
+- hosts: switch_vbng
+ sudo: yes
+ vars:
+ controller_ip: "{{ hostvars['onos_vbng']['ansible_ssh_host'] }}"
+ controller_port: 6653
+ ovs_dpid: "0000000000000001"
+ tags:
+ - vbng
+ tasks:
+ - name: Fix /etc/hosts
+ lineinfile:
+ dest=/etc/hosts
+ regexp="127.0.0.1 localhost"
+ line="127.0.0.1 localhost {{ ansible_hostname }}"
+
+ - name: Install packages
+ apt: name={{ item }}
+ state=latest
+ update_cache=yes
+ with_items:
+ - openvswitch-switch
+ - python-netifaces
+
+ - name: Create br-vbng
+ openvswitch_bridge:
+ bridge=br-vbng
+ state=present
+
+ - name: Find wan_network interface
+ script: scripts/if_from_ip.py {{ wan_ip }}
+ register: wan_net
+
+ - name: Find public_network interface
+ script: scripts/if_from_ip.py {{ public_ip }}
+ register: public_net
+
+ - name: Hook up wan-network to br-vbng
+ openvswitch_port:
+ bridge=br-vbng
+ port={{ wan_net.stdout }}
+ state=present
+
+ - name: Hook up public-network to OvS
+ openvswitch_port:
+ bridge=br-vbng
+ port={{ public_net.stdout }}
+ state=present
+
+ - name: Change datapath ID of bridge to match config file
+ command: /usr/bin/ovs-vsctl set bridge br-vbng other-config:datapath-id={{ ovs_dpid }}
+
+ - name: Add controller to switch
+ command: /usr/bin/ovs-vsctl set-controller br-vbng tcp:{{ controller_ip }}:{{ controller_port }}
+
+- hosts: switch_volt
+ sudo: yes
+ vars:
+ controller_ip: "{{ hostvars['onos_volt']['ansible_ssh_host'] }}"
+ controller_port: 6653
+ tags:
+ - volt
+ tasks:
+
+ - name: Fix /etc/hosts
+ lineinfile:
+ dest=/etc/hosts
+ regexp="127.0.0.1 localhost"
+ line="127.0.0.1 localhost {{ ansible_hostname }}"
+
+ - name: Install packages
+ apt: name={{ item }} state=present update_cache=yes
+ with_items:
+ - git
+ - python-netifaces
+
+ - name: Checkout the Mininet repo
+ git: repo=https://github.com/mininet/mininet.git
+ dest=/tmp/mininet
+
+ - name: Install the CPqD switch using Mininet install script
+ shell: /tmp/mininet/util/install.sh -3f
+ creates=/usr/local/bin/ofdatapath
+ ignore_errors: true
+
+ - name: Find subscriber_network interface
+ script: scripts/if_from_ip.py {{ subscriber_ip }}
+ register: subscriber_net
+
+ - name: Find lan_network interface
+ script: scripts/if_from_ip.py {{ lan_ip }}
+ register: lan_net
+
+ - name: Run the datapath
+ command: /usr/local/bin/ofdatapath -i {{ subscriber_net.stdout_lines[0] }},{{ lan_net.stdout_lines[0] }} punix:/tmp/s1 -d 000000000001 --no-slicing -D -P
+ creates=/usr/local/var/run/ofdatapath.pid
+
+ - name: Run the control program
+ command: /usr/local/bin/ofprotocol unix:/tmp/s1 tcp:{{ controller_ip }}:{{ controller_port }} --fail=closed --listen=punix:/tmp/s1.listen -D -P
+ creates=/usr/local/var/run/ofprotocol.pid
diff --git a/xos/configurations/cord/dataplane/generate.sh b/xos/configurations/cord/dataplane/generate.sh
new file mode 100755
index 0000000..360ed67
--- /dev/null
+++ b/xos/configurations/cord/dataplane/generate.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+# set -x
+
+source ~/admin-openrc.sh
+
+get_ip () {
+ LABEL=$1
+ NETWORK=$2
+ nova list --all-tenants|grep $LABEL|sed "s/^.*$NETWORK=//g"|sed 's/; .*$//g'|awk '{print $1}'
+}
+
+cat <<EOF
+onos_vbng ansible_ssh_host=$( get_ip mysite_onos_vbng flat-lan-1-net)
+switch_vbng ansible_ssh_host=$( get_ip mysite_vbng flat-lan-1-net) wan_ip=$( get_ip mysite_vbng wan_network) public_ip=$( get_ip mysite_vbng tun0-net )
+
+onos_volt ansible_ssh_host=$( get_ip mysite_onos_volt flat-lan-1-net)
+switch_volt ansible_ssh_host=$( get_ip mysite_volt flat-lan-1-net) subscriber_ip=$( get_ip mysite_volt subscriber_network) lan_ip=$( get_ip mysite_volt lan_network) vcpe_lan_ip=$( get_ip mysite_vcpe lan_network)
+EOF
diff --git a/xos/configurations/cord/dataplane/scripts/if_from_ip.py b/xos/configurations/cord/dataplane/scripts/if_from_ip.py
new file mode 100644
index 0000000..be1da48
--- /dev/null
+++ b/xos/configurations/cord/dataplane/scripts/if_from_ip.py
@@ -0,0 +1,14 @@
+#!/usr/bin/python
+
+import sys
+import netifaces
+
+def main (argv):
+ addr = argv[0]
+ for iface in netifaces.interfaces():
+ addrs = netifaces.ifaddresses(iface)
+ if 2 in addrs and addrs[2][0]['addr'] == addr:
+ print iface
+
+if __name__ == "__main__":
+ main(sys.argv[1:])
diff --git a/xos/configurations/cord/etc_xos_metering.tar.gz b/xos/configurations/cord/etc_xos_metering.tar.gz
new file mode 100644
index 0000000..53689db
--- /dev/null
+++ b/xos/configurations/cord/etc_xos_metering.tar.gz
Binary files differ
diff --git a/xos/configurations/cord/install_ceilometer_vcpe_notification_listener.sh b/xos/configurations/cord/install_ceilometer_vcpe_notification_listener.sh
new file mode 100755
index 0000000..50a4132
--- /dev/null
+++ b/xos/configurations/cord/install_ceilometer_vcpe_notification_listener.sh
@@ -0,0 +1,16 @@
+if [ -d /usr/lib/python2.7/dist-packages/ceilometer/network/ext_services ]; then
+ echo "Seems VCPE notification listeners are already enabled in ceilometer... so exiting gracefully..."
+ exit 0
+fi
+echo "Verifying if all the required files are present"
+if [ ! -f ceilometer_vcpe_notification_agent.tar.gz ];
+then
+ echo "File ceilometer_vcpe_notification_agent.tar.gz not found"
+ exit 1
+fi
+echo "Copying the ceilometer vcpe notification agent files /usr/lib/python2.7/dist-packages/ceilometer"
+tar -xzf ceilometer_vcpe_notification_agent.tar.gz
+sudo mv ceilometer/network/ext_services /usr/lib/python2.7/dist-packages/ceilometer/network/
+sudo mv ceilometer-2015.1.1.egg-info/entry_points.txt /usr/lib/python2.7/dist-packages/ceilometer-2015.1.1.egg-info/
+echo "Restarting ceilometer-agent-notification"
+sudo service ceilometer-agent-notification restart
diff --git a/xos/configurations/cord/install_xos_ceilometer_dashboard.sh b/xos/configurations/cord/install_xos_ceilometer_dashboard.sh
new file mode 100755
index 0000000..ed72f54
--- /dev/null
+++ b/xos/configurations/cord/install_xos_ceilometer_dashboard.sh
@@ -0,0 +1,25 @@
+if [ -d /usr/share/xos-metering ]; then
+ echo "Seems xos ceilometer dashboard is already installed... so exiting gracefully..."
+ exit 0
+fi
+echo "Verifying if all the required files are present"
+if [ ! -f xos_metering_dashboard.tar.gz ];
+then
+ echo "File xos_metering_dashboard.tar.gz not found"
+ exit 1
+fi
+if [ ! -f etc_xos_metering.tar.gz ];
+then
+ echo "File etc_xos_metering.tar.gz not found"
+ exit 1
+fi
+echo "Copying the xos ceilometer dashboard files /usr/share/ and /etc/apache2/"
+tar -xzf xos_metering_dashboard.tar.gz
+sudo mv xos-metering /usr/share/
+tar -xzf etc_xos_metering.tar.gz
+sudo mv xos-metering /etc/
+sudo mv apache2/conf-available/xos-metering.conf /etc/apache2/conf-available/
+cd /etc/apache2/conf-enabled/
+sudo ln -s ../conf-available/xos-metering.conf xos-metering.conf
+echo "Restarting apache2"
+sudo service apache2 restart
diff --git a/xos/configurations/cord/xos_metering_dashboard.tar.gz b/xos/configurations/cord/xos_metering_dashboard.tar.gz
new file mode 100644
index 0000000..648f91a
--- /dev/null
+++ b/xos/configurations/cord/xos_metering_dashboard.tar.gz
Binary files differ
diff --git a/xos/configurations/devel/Dockerfile.devel b/xos/configurations/devel/Dockerfile.devel
index e44891a..115b731 100644
--- a/xos/configurations/devel/Dockerfile.devel
+++ b/xos/configurations/devel/Dockerfile.devel
@@ -1,8 +1,12 @@
RUN mkdir -p /root/setup
ADD xos/configurations/common/admin-openrc.sh /root/setup/
+ADD xos/configurations/common/controller_settings /root/setup/
ADD xos/configurations/common/flat_net_name /root/setup/
ADD xos/configurations/common/cloudlab-nodes.yaml /opt/xos/configurations/commmon/
ADD xos/configurations/common/id_rsa.pub /root/setup/padmin_public_key
+ADD xos/configurations/common/node_key.pub /root/setup/node_key.pub
+ADD xos/configurations/common/node_key /root/setup/node_key
+ADD xos/configurations/common/ceilometer_url /root/setup/ceilometer_url
CMD /usr/bin/make -C /opt/xos/configurations/devel -f Makefile.inside; /bin/bash
diff --git a/xos/configurations/frontend/Makefile b/xos/configurations/frontend/Makefile
index e73c6ad..500e932 100644
--- a/xos/configurations/frontend/Makefile
+++ b/xos/configurations/frontend/Makefile
@@ -10,7 +10,7 @@
cat ../common/Dockerfile.common Dockerfile.frontend > Dockerfile
cd ../../..; sudo docker build -t xos -f xos/configurations/frontend/Dockerfile .
echo $(XOS_FOLDER)
- sudo docker run -v $(XOS_FOLDER)/../../core/xoslib:/opt/xos/core/xoslib -p 9000:8000 --add-host="0.0.0.0:127.0.0.1" xos
+ sudo docker run -v $(XOS_FOLDER)/../../core/xoslib:/opt/xos/core/xoslib -p 9999:8000 --add-host="0.0.0.0:127.0.0.1" xos
#sudo docker run -d --add-host="0.0.0.0:$(MYIP)" -p 9999:8000 xos
bash ../common/wait_for_xos.sh
echo $(RUNNING_CONTAINER)
diff --git a/xos/configurations/opencloud/Dockerfile b/xos/configurations/opencloud/Dockerfile
deleted file mode 100644
index 5b09507..0000000
--- a/xos/configurations/opencloud/Dockerfile
+++ /dev/null
@@ -1,149 +0,0 @@
-FROM ubuntu:14.04.2
-MAINTAINER Andy Bavier <acb@cs.princeton.edu>
-
-# Set environment variables.
-ENV HOME /root
-ENV TOSCA_CONFIG_PATH=/opt/xos/configurations/opencloud/opencloud.tosca
-
-# XXX Workaround for docker bug:
-# https://github.com/docker/docker/issues/6345
-# Kernel 3.15 breaks docker, uss the line below as a workaround
-# until there is a fix
-RUN ln -s -f /bin/true /usr/bin/chfn
-# XXX End workaround
-
-# Install.
-RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y \
- git \
- postgresql \
- graphviz \
- graphviz-dev \
- libxslt1.1 \
- libxslt1-dev \
- tar \
- gcc \
- geoip-database \
- libgeoip1 \
- openssh-client \
- wget \
- curl \
- python-dev \
- libyaml-dev \
- pkg-config \
- supervisor \
- python-crypto \
- python-httplib2>=0.9.1 \
- python-jinja2 \
- python-paramiko \
- python-pip \
- python-psycopg2 \
- python-pycurl \
- python-setuptools \
- python-yaml \
- python-keystoneclient \
- python-novaclient \
- python-neutronclient \
- python-glanceclient \
- python-ceilometerclient
-
-RUN pip install \
- django==1.7 \
- djangorestframework==2.4.4 \
- markdown \
- pyyaml \
- django-filter \
- lxml \
- netaddr \
- pytz \
- django-timezones \
- requests \
- django-crispy-forms \
- django-geoposition \
- django-extensions \
- django-suit \
- django-bitfield \
- django-ipware \
- django-encrypted-fields \
- django_rest_swagger \
- python-keyczar \
- pygraphviz \
- dnslib
-
-RUN easy_install --upgrade httplib2
-
-RUN easy_install \
- django_evolution \
- python_gflags \
- google_api_python_client \
- httplib2.ca_certs_locater
-
-
-# Install custom Ansible
-RUN git clone -b release1.8.2 git://github.com/ansible/ansible.git /opt/ansible
-RUN git clone -b release1.8.2 git://github.com/ansible/ansible-modules-extras.git /opt/ansible/lib/ansible/modules/extras
-RUN git clone -b release1.8.2 git://github.com/ansible/ansible-modules-extras.git /opt/ansible/v2/ansible/modules/extras
-RUN git clone git://github.com/sb98052/ansible-modules-core.git /opt/ansible/lib/ansible/modules/core
-RUN git clone git://github.com/sb98052/ansible-modules-core.git /opt/ansible/v2/ansible/modules/core
-ADD ansible-hosts /etc/ansible/hosts
-
-ADD http://code.jquery.com/jquery-1.9.1.min.js /usr/local/lib/python2.7/dist-packages/suit/static/suit/js/
-
-# For Observer
-RUN git clone git://git.planet-lab.org/fofum.git /tmp/fofum
-RUN cd /tmp/fofum; python setup.py install
-RUN rm -rf /tmp/fofum
-
-RUN mkdir -p /usr/local/share /bin
-ADD http://phantomjs.googlecode.com/files/phantomjs-1.7.0-linux-x86_64.tar.bz2 /usr/local/share/
-RUN tar jxvf /usr/local/share/phantomjs-1.7.0-linux-x86_64.tar.bz2 -C /usr/local/share/
-RUN rm -f /usr/local/share/phantomjs-1.7.0-linux-x86_64.tar.bz2
-RUN ln -s /usr/local/share/phantomjs-1.7.0-linux-x86_64 /usr/local/share/phantomjs
-RUN ln -s /usr/local/share/phantomjs/bin/phantomjs /bin/phantomjs
-
-# Supervisor
-ADD observer.conf /etc/supervisor/conf.d/
-
-# Get XOS
-RUN git clone git://github.com/open-cloud/xos.git /tmp/xos && mv /tmp/xos/xos /opt/
-
-# Initscript is broken in Ubuntu
-#ADD observer-initscript /etc/init.d/xosobserver
-
-RUN chmod +x /opt/xos/scripts/opencloud
-RUN /opt/xos/scripts/opencloud genkeys
-
-# Workaround for AUFS issue
-# https://github.com/docker/docker/issues/783#issuecomment-56013588
-RUN mkdir /etc/ssl/private-copy; mv /etc/ssl/private/* /etc/ssl/private-copy/; rm -r /etc/ssl/private; mv /etc/ssl/private-copy /etc/ssl/private; chmod -R 0700 /etc/ssl/private; chown -R postgres /etc/ssl/private
-
-# Set postgres password to match default value in settings.py
-RUN service postgresql start; sudo -u postgres psql -c "alter user postgres with password 'password';"
-
-# Turn DEBUG on so that devel server will serve static files
-# (not necessary if --insecure is passed to 'manage.py runserver')
-# RUN sed -i 's/DEBUG = False/DEBUG = True/' /opt/xos/xos/settings.py
-
-# Cruft to workaround problems with migrations, should go away...
-RUN /opt/xos/scripts/opencloud remigrate
-
-# git clone uses cached copy, doesn't pick up latest
-RUN git -C /opt/ansible pull
-RUN git -C /opt/ansible/lib/ansible/modules/core pull
-RUN git -C /opt/ansible/v2/ansible/modules/core pull
-
-# install Tosca engine
-RUN apt-get install -y m4
-RUN pip install python-dateutil
-RUN bash /opt/xos/tosca/install_tosca.sh
-
-EXPOSE 8000
-
-# Set environment variables.
-ENV HOME /root
-
-# Define working directory.
-WORKDIR /root
-
-# Define default command.
-#CMD ["/bin/bash"]
-CMD /opt/xos/scripts/docker_start_xos
diff --git a/xos/configurations/opencloud/Makefile b/xos/configurations/opencloud/Makefile
deleted file mode 100644
index 863f2b7..0000000
--- a/xos/configurations/opencloud/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-RUNNING_CONTAINER:=$(shell sudo docker ps|grep "opencloud_server"|awk '{print $$NF}')
-
-.PHONY: build
-build: ; docker build --rm -t opencloud .
-
-.PHONY: run
-run: ; docker run --rm --name opencloud_server opencloud
-
-.PHONY: runtosca
-runtosca: ; docker exec -it $RUNNING_CONTAINER /usr/bin/python /opt/xos/tosca/run.py padmin@vicci.org $TOSCA_CONFIG_PATH
-
-.PHONY: stop
-stop: ; docker stop opencloud_server
-
-.PHONY: rmcontainer
-rmcontainer: ; docker rm opencloud_server
diff --git a/xos/configurations/opencloud/Makefile.inside b/xos/configurations/opencloud/Makefile.inside
deleted file mode 100644
index 43ad235..0000000
--- a/xos/configurations/opencloud/Makefile.inside
+++ /dev/null
@@ -1,2 +0,0 @@
-run_tosca:
- python /opt/xos/tosca/run.py padmin@vicci.org opencloud.yaml
diff --git a/xos/configurations/opencloud/observer.conf b/xos/configurations/opencloud/observer.conf
deleted file mode 100644
index 92545eb..0000000
--- a/xos/configurations/opencloud/observer.conf
+++ /dev/null
@@ -1,2 +0,0 @@
-[program:observer]
-command=python /opt/xos/xos-observer.py
diff --git a/xos/configurations/opencloud/opencloud.yaml b/xos/configurations/opencloud/opencloud.yaml
index f6d33a2..15142a6 100644
--- a/xos/configurations/opencloud/opencloud.yaml
+++ b/xos/configurations/opencloud/opencloud.yaml
@@ -1,7 +1,6 @@
tosca_definitions_version: tosca_simple_yaml_1_0
-description: >
- * Adds OpenCloud Sites, Deployments, and Controllers.
+description: Adds OpenCloud Sites, Deployments, and Controllers.
imports:
- custom_types/xos.yaml
@@ -188,7 +187,7 @@
admin_tenant: admin
domain: Default
- backbone-wdc:
+ backbone-wdc:
type: tosca.nodes.Controller
requirements:
- deployment:
@@ -203,11 +202,26 @@
admin_tenant: admin
domain: Default
+ campus-arizona:
+ type: tosca.nodes.Controller
+ requirements:
+ - deployment:
+ node: campus
+ relationship: tosca.relationships.ControllerDeployment
+ properties:
+ backend_type: OpenStack
+ version: Juno
+ auth_url: http://localhost:35357/v2.0/
+ admin_user: admin
+ admin_password: admin
+ admin_tenant: admin
+ domain: Default
+
campus-princeton:
type: tosca.nodes.Controller
requirements:
- deployment:
- node: backbone
+ node: campus
relationship: tosca.relationships.ControllerDeployment
properties:
backend_type: OpenStack
@@ -222,7 +236,7 @@
type: tosca.nodes.Controller
requirements:
- deployment:
- node: backbone
+ node: campus
relationship: tosca.relationships.ControllerDeployment
properties:
backend_type: OpenStack
@@ -237,7 +251,7 @@
type: tosca.nodes.Controller
requirements:
- deployment:
- node: backbone
+ node: campus
relationship: tosca.relationships.ControllerDeployment
properties:
backend_type: OpenStack
@@ -252,7 +266,7 @@
type: tosca.nodes.Controller
requirements:
- deployment:
- node: backbone
+ node: campus
relationship: tosca.relationships.ControllerDeployment
properties:
backend_type: OpenStack
@@ -267,7 +281,7 @@
type: tosca.nodes.Controller
requirements:
- deployment:
- node: backbone
+ node: campus
relationship: tosca.relationships.ControllerDeployment
properties:
backend_type: OpenStack
@@ -282,7 +296,7 @@
type: tosca.nodes.Controller
requirements:
- deployment:
- node: backbone
+ node: campus
relationship: tosca.relationships.ControllerDeployment
properties:
backend_type: OpenStack
@@ -297,7 +311,7 @@
type: tosca.nodes.Controller
requirements:
- deployment:
- node: backbone
+ node: campus
relationship: tosca.relationships.ControllerDeployment
properties:
backend_type: OpenStack
@@ -363,7 +377,7 @@
relationship: tosca.relationships.SiteDeployment
requirements:
- controller:
- node: backbone-kas
+ node: backbone-kan
relationship: tosca.relationships.UsesController
i2-lax:
@@ -436,7 +450,7 @@
node: backbone-sng
relationship: tosca.relationships.UsesController
- i2-wdc:
+ i2-wdc:
type: tosca.nodes.Site
properties:
display_name: I2-wdc
@@ -567,7 +581,7 @@
type: tosca.nodes.User
requirements:
- site:
- node: campus_princeton
+ node: princeton
relationship: tosca.relationships.MemberOfSite
properties:
is_admin: true
diff --git a/xos/cord/models.py b/xos/cord/models.py
index 26d7d24..67ffdc7 100644
--- a/xos/cord/models.py
+++ b/xos/cord/models.py
@@ -465,7 +465,7 @@
sync_attributes = ("nat_ip", "nat_mac",
"lan_ip", "lan_mac",
- "wan_ip", "wan_mac",
+ "wan_ip", "wan_mac", "wan_container_mac",
"private_ip", "private_mac",
"hpc_client_ip", "hpc_client_mac")
@@ -575,6 +575,12 @@
def wan_mac(self):
return self.addresses.get("wan", (None, None) )[1]
+ # Generate the MAC for the container interface connected to WAN
+ @property
+ def wan_container_mac(self):
+ (a, b, c, d) = self.wan_ip.split('.')
+ return "02:42:%02x:%02x:%02x:%02x" % (int(a), int(b), int(c), int(d))
+
@property
def private_ip(self):
return self.addresses.get("private", (None, None) )[0]
diff --git a/xos/core/admin.py b/xos/core/admin.py
index a5b89be..a0cabd1 100644
--- a/xos/core/admin.py
+++ b/xos/core/admin.py
@@ -1372,6 +1372,39 @@
# obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
# obj.delete()
+class ContainerPortInline(XOSTabularInline):
+ fields = ['backend_status_icon', 'network', 'container', 'ip', 'mac', 'segmentation_id']
+ readonly_fields = ("backend_status_icon", "ip", "mac", "segmentation_id")
+ model = Port
+ selflink_fieldname = "network"
+ extra = 0
+ verbose_name_plural = "Ports"
+ verbose_name = "Port"
+ suit_classes = 'suit-tab suit-tab-ports'
+
+class ContainerAdmin(XOSBaseAdmin):
+ fieldsets = [
+ ('Container Details', {'fields': ['backend_status_text', 'slice', 'node', 'docker_image', 'no_sync'], 'classes': ['suit-tab suit-tab-general'], })
+ ]
+ readonly_fields = ('backend_status_text', )
+ list_display = ['backend_status_icon', 'id']
+ list_display_links = ('backend_status_icon', 'id', )
+
+ suit_form_tabs =(('general', 'Container Details'), ('ports', 'Ports'))
+
+ inlines = [TagInline, ContainerPortInline]
+
+ def formfield_for_foreignkey(self, db_field, request, **kwargs):
+ if db_field.name == 'slice':
+ kwargs['queryset'] = Slice.select_by_user(request.user)
+
+ return super(ContainerAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
+
+ def queryset(self, request):
+ # admins can see all instances. Users can only see instances of
+ # the slices they belong to.
+ return Container.select_by_user(request.user)
+
class UserCreationForm(forms.ModelForm):
"""A form for creating new users. Includes all the required
fields, plus a repeated password."""
@@ -1727,7 +1760,7 @@
readonly_fields = ('backend_status_icon', )
class NetworkPortInline(XOSTabularInline):
- fields = ['backend_status_icon', 'network', 'instance', 'ip', 'mac']
+ fields = ['backend_status_icon', 'network', 'instance', 'container', 'ip', 'mac']
readonly_fields = ("backend_status_icon", "ip", "mac")
model = Port
selflink_fieldname = "instance"
@@ -2024,4 +2057,5 @@
admin.site.register(TenantRoot, TenantRootAdmin)
admin.site.register(TenantRootRole, TenantRootRoleAdmin)
admin.site.register(TenantAttribute, TenantAttributeAdmin)
+ admin.site.register(Container, ContainerAdmin)
diff --git a/xos/core/models/__init__.py b/xos/core/models/__init__.py
index c380e9c..bc97dab 100644
--- a/xos/core/models/__init__.py
+++ b/xos/core/models/__init__.py
@@ -24,6 +24,7 @@
from .node import Node
from .slicetag import SliceTag
from .instance import Instance
+from .container import Container
from .reservation import ReservedResource
from .reservation import Reservation
from .network import Network, NetworkParameterType, NetworkParameter, Port, NetworkTemplate, Router, NetworkSlice, ControllerNetwork
diff --git a/xos/core/models/container.py b/xos/core/models/container.py
new file mode 100644
index 0000000..151b576
--- /dev/null
+++ b/xos/core/models/container.py
@@ -0,0 +1,83 @@
+import os
+from django.db import models
+from django.db.models import Q
+from django.core import exceptions
+from core.models import PlCoreBase,PlCoreBaseManager,PlCoreBaseDeletionManager
+from core.models.plcorebase import StrippedCharField
+from core.models import Image
+from core.models import Slice, SlicePrivilege
+from core.models import Node
+from core.models import Site
+from core.models import Deployment
+from core.models import Controller
+from core.models import User
+from core.models import Tag
+from core.models import Flavor
+from django.contrib.contenttypes import generic
+from xos.config import Config
+from monitor import driver as monitor
+from django.core.exceptions import PermissionDenied, ValidationError
+
+config = Config()
+
+
+# Create your models here.
+class Container(PlCoreBase):
+ name = StrippedCharField(max_length=200, help_text="Container name")
+ slice = models.ForeignKey(Slice, related_name='containers')
+ node = models.ForeignKey(Node, related_name='containers')
+ creator = models.ForeignKey(User, related_name='containers', blank=True, null=True)
+ docker_image = StrippedCharField(null=True, blank=True, max_length=200, help_text="name of docker container to instantiate")
+
+ def __unicode__(self):
+ return u'container-%s' % str(self.id)
+
+ def save(self, *args, **kwds):
+ if not self.name:
+ self.name = self.slice.name
+ if not self.creator and hasattr(self, 'caller'):
+ self.creator = self.caller
+ if not self.creator:
+ raise ValidationError('container has no creator')
+
+ if (self.slice.creator != self.creator):
+ # Check to make sure there's a slice_privilege for the user. If there
+ # isn't, then keystone will throw an exception inside the observer.
+ slice_privs = SlicePrivilege.objects.filter(slice=self.slice, user=self.creator)
+ if not slice_privs:
+ raise ValidationError('container creator has no privileges on slice')
+
+# XXX smbaker - disabled for now, was causing fault in tenant view create slice
+# if not self.controllerNetwork.test_acl(slice=self.slice):
+# raise exceptions.ValidationError("Deployment %s's ACL does not allow any of this slice %s's users" % (self.controllerNetwork.name, self.slice.name))
+
+ super(Container, self).save(*args, **kwds)
+
+ def can_update(self, user):
+ return True
+
+ @staticmethod
+ def select_by_user(user):
+ if user.is_admin:
+ qs = Container.objects.all()
+ else:
+ slices = Slice.select_by_user(user)
+ qs = Container.objects.filter(slice__in=slices)
+ return qs
+
+ def get_public_keys(self):
+ slice_memberships = SlicePrivilege.objects.filter(slice=self.slice)
+ pubkeys = set([sm.user.public_key for sm in slice_memberships if sm.user.public_key])
+
+ if self.creator.public_key:
+ pubkeys.add(self.creator.public_key)
+
+ if self.slice.creator.public_key:
+ pubkeys.add(self.slice.creator.public_key)
+
+ if self.slice.service and self.slice.service.public_key:
+ pubkeys.add(self.slice.service.public_key)
+
+ return pubkeys
+
+
diff --git a/xos/core/models/network.py b/xos/core/models/network.py
index 2bdf17f..48af5a6 100644
--- a/xos/core/models/network.py
+++ b/xos/core/models/network.py
@@ -2,7 +2,7 @@
import socket
import sys
from django.db import models
-from core.models import PlCoreBase, Site, Slice, Instance, Controller
+from core.models import PlCoreBase, Site, Slice, Instance, Controller, Container
from core.models import ControllerLinkManager,ControllerLinkDeletionManager
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic
@@ -158,7 +158,7 @@
router_id = models.CharField(null=True, blank=True, max_length=256, help_text="Quantum router id")
subnet_id = models.CharField(null=True, blank=True, max_length=256, help_text="Quantum subnet id")
subnet = models.CharField(max_length=32, blank=True)
-
+
class Meta:
unique_together = ('network', 'controller')
@@ -211,9 +211,12 @@
class Port(PlCoreBase):
network = models.ForeignKey(Network,related_name='links')
instance = models.ForeignKey(Instance, null=True, blank=True, related_name='ports')
+ container = models.ForeignKey(Container, null=True, blank=True, related_name='ports')
ip = models.GenericIPAddressField(help_text="Instance ip address", blank=True, null=True)
port_id = models.CharField(null=True, blank=True, max_length=256, help_text="Quantum port id")
mac = models.CharField(null=True, blank=True, max_length=256, help_text="MAC address associated with this port")
+ #unattached = models.BooleanField(default=False, help_text="create this port even if no Instance is attached")
+ segmentation_id = models.CharField(null=True, blank=True, max_length=256, help_text="GRE segmentation id for port")
class Meta:
unique_together = ('network', 'instance')
diff --git a/xos/core/static/xos.css b/xos/core/static/xos.css
index 96ca8b1..33d05cb 100644
--- a/xos/core/static/xos.css
+++ b/xos/core/static/xos.css
@@ -1,4 +1,4 @@
-/*************************
+g/*************************
colors:
tab - active/focus color
background-color: #105E9E !important;
@@ -483,7 +483,8 @@
.login #content-main h1 {
/*background: #EBF0F2;*/
-background: url("open-cloud-login-themed-light.png") no-repeat scroll 40% center / 89% auto rgba(235, 240, 242, 0);
+/*background: url("open-cloud-login-themed-light.png") no-repeat scroll 40% center / 89% auto rgba(235, 240, 242, 0);*/
+background: url("cord_logo_3.png") no-repeat scroll 40% center / 89% auto rgba(235, 240, 242, 0);
/*background-position: 40%;*/
height: 55px;
background-repeat: no-repeat;
diff --git a/xos/core/xoslib/spec/views/contentprovider.test.js b/xos/core/xoslib/spec/views/contentprovider.test.js
index e522534..7b64ae8 100644
--- a/xos/core/xoslib/spec/views/contentprovider.test.js
+++ b/xos/core/xoslib/spec/views/contentprovider.test.js
@@ -2,13 +2,18 @@
describe('The Content Provider SPA', () => {
- var scope, element, isolatedScope, httpBackend, mockLocation;
+ var scope, element, isolatedScope, httpBackend, mockLocation, httpProvider;
+
+ var token = 'fakeToken';
// injecting main module
beforeEach(module('xos.contentProviderApp'));
beforeEach(function(){
- module(function($provide){
+ module(function($provide, $httpProvider){
+
+ httpProvider = $httpProvider;
+
// mocking routeParams to pass 1 as id
$provide.provider('$routeParams', function(){
/* eslint-disable no-invalid-this*/
@@ -17,6 +22,15 @@
};
/* eslint-enable no-invalid-this*/
});
+
+ //mock $cookie to return a fake xoscsrftoken
+ $provide.service('$cookies', function(){
+ /* eslint-disable no-invalid-this*/
+ this.get = () => {
+ return token;
+ };
+ /* eslint-enable no-invalid-this*/
+ });
});
});
@@ -30,6 +44,25 @@
$httpBackend.whenDELETE('/hpcapi/contentproviders/1/?no_hyperlinks=1').respond();
}));
+ it('should set the $http interceptor', () => {
+ expect(httpProvider.interceptors).toContain('SetCSRFToken');
+ });
+
+ it('should add no_hyperlink param', inject(($http, $httpBackend) => {
+ $http.get('www.example.com');
+ $httpBackend.expectGET('www.example.com?no_hyperlinks=1').respond(200);
+ $httpBackend.flush();
+ }));
+
+ it('should set token in the headers', inject(($http, $httpBackend) => {
+ $http.post('http://example.com');
+ $httpBackend.expectPOST('http://example.com?no_hyperlinks=1', undefined, function(headers){
+ // if this condition is false the httpBackend expectation fail
+ return headers['X-CSRFToken'] === token;
+ }).respond(200, {name: 'example'});
+ httpBackend.flush();
+ }));
+
describe('the action directive', () => {
beforeEach(inject(function($compile, $rootScope){
scope = $rootScope.$new();
diff --git a/xos/core/xoslib/static/js/xoslib/xos-backbone.js b/xos/core/xoslib/static/js/xoslib/xos-backbone.js
index 61f51b4..04d5fb7 100644
--- a/xos/core/xoslib/static/js/xoslib/xos-backbone.js
+++ b/xos/core/xoslib/static/js/xoslib/xos-backbone.js
@@ -893,8 +893,10 @@
var _sync = Backbone.sync;
Backbone.sync = function(method, model, options){
options.beforeSend = function(xhr){
- var token = getCookie("csrftoken");
- xhr.setRequestHeader('X-CSRFToken', token);
+ // var token = getCookie("csrftoken");
+ // xhr.setRequestHeader('X-CSRFToken', token);
+ var xosToken = getCookie('xoscsrftoken');
+ xhr.setRequestHeader('X-CSRFToken', xosToken);
};
return _sync(method, model, options);
};
diff --git a/xos/core/xoslib/xos-builder/.gitignore b/xos/core/xoslib/xos-builder/.gitignore
index 5157e54..bccda71 100644
--- a/xos/core/xoslib/xos-builder/.gitignore
+++ b/xos/core/xoslib/xos-builder/.gitignore
@@ -1,3 +1,5 @@
dist/
src/vendor
-.tmp
\ No newline at end of file
+.tmp
+node_modules
+npm-debug.log
\ No newline at end of file
diff --git a/xos/core/xoslib/xos-builder/README.md b/xos/core/xoslib/xos-builder/README.md
new file mode 100644
index 0000000..7e15de6
--- /dev/null
+++ b/xos/core/xoslib/xos-builder/README.md
@@ -0,0 +1,46 @@
+# XOS Lib Helper
+
+This library should help you while developing with:
+
+#### Serve
+- Install Bower deps
+- Load js files (from args folder)
+- Load html templates (from args folder)
+- Compile ES6
+- Compile Scss
+- Compile template using `ng2html`
+- Watch source folder
+- Livereload
+- Generate a basic index.html in a `dist` folder under `args` folder loading files
+
+#### Build
+- Install Bower deps
+- Load js files (from args folder)
+- Load html templates (from args folder)
+- Compile ES6
+- Compile Scss
+- Compile template using `ng2html`
+- Minify Js & Css
+- Prefix Css
+- Cicle trough `bower.json` and diff it with base `bower.json` to exclude already loaded modules (eg: angular) [Optional]
+- Move `dist` under xos folder
+
+## App Structure
+
+App Name
+â””- src
+ ├ js
+ ├ templates
+ ├ bower_components
+ â”” dist
+
+Angular apps should be saved under `xoslib/source` and builded apps should be moved under `xoslib/static/js`.
+
+Two files should be generated, `appname_main.js` and `appname_vendor.js`, these file should be included into `xoslib/dashboards/appname.html` (tbd if this file has to be automatically generated during the build)
+
+## Advantages
+
+- Faster development with common tool
+- Standard build for community developer
+- Minified files
+
diff --git a/xos/core/xoslib/xos-builder/xos-builder.js b/xos/core/xoslib/xos-builder/xos-builder.js
new file mode 100755
index 0000000..d6adfe5
--- /dev/null
+++ b/xos/core/xoslib/xos-builder/xos-builder.js
@@ -0,0 +1,20 @@
+#! /usr/bin/env node
+'use strict';
+
+const assert = require('assert');
+const chalk = require('chalk');
+
+const args = process.argv.slice(2);
+
+const error = chalk.white.bgRed;
+const success = chalk.white.bgGreen;
+
+const task = args[0];
+if(!task){
+ console.log(error('A task should be defined'))
+ process.exit(1);
+}
+
+console.log(success('Build Started for'));
+
+console.log(process.argv);
diff --git a/xos/nginx/xos.conf b/xos/nginx/xos.conf
index 9b5d996..64d9d5e 100644
--- a/xos/nginx/xos.conf
+++ b/xos/nginx/xos.conf
@@ -6,8 +6,9 @@
server {
- listen 80;
- server_name 128.112.139.48;
+ listen 80;
+ listen [::]:80 default ipv6only=on; ## listen for ipv6
+ server_name 127.0.0.1;
location /static/ {
alias /opt/xos/core/static/;
diff --git a/xos/observers/onos/steps/sync_onosapp.yaml b/xos/observers/onos/steps/sync_onosapp.yaml
index 2c5eb0f..ad3718c 100644
--- a/xos/observers/onos/steps/sync_onosapp.yaml
+++ b/xos/observers/onos/steps/sync_onosapp.yaml
@@ -11,39 +11,44 @@
tasks:
- name: Config file directory
- file:
- path=/home/ubuntu/{{ appname }}/
- state=directory
-
- - name: Copy over configuration files
- copy:
- src={{ files_dir }}/{{ '{{' }} item {{ '}}' }}
- dest=/home/ubuntu/{{ appname }}/{{ '{{' }} item {{ '}}' }}
- with_items:
- {% for config_fn in config_fns %}
+ file:
+ path=/home/ubuntu/{{ appname }}/
+ state=directory
+
+{% if config_fns %}
+ - name: Copy over configuration files
+ copy:
+ src={{ files_dir }}/{{ '{{' }} item {{ '}}' }}
+ dest=/home/ubuntu/{{ appname }}/{{ '{{' }} item {{ '}}' }}
+ with_items:
+ {% for config_fn in config_fns %}
- {{ config_fn }}
- {% endfor %}
-
- - name: Copy config files into container
- shell: docker cp {{ appname }}/{{ '{{' }} item {{ '}}' }} {{ ONOS_container }}:/root/onos/config/
- sudo: yes
- with_items:
- {% for config_fn in config_fns %}
+ {% endfor %}
+
+ - name: Make sure config directory exists
+ shell: docker exec {{ ONOS_container }} mkdir -p /root/onos/config/
+ sudo: yes
+
+ - name: Copy config files into container
+ shell: docker cp {{ appname }}/{{ '{{' }} item {{ '}}' }} {{ ONOS_container }}:/root/onos/config/
+ sudo: yes
+ with_items:
+ {% for config_fn in config_fns %}
- {{ config_fn }}
- {% endfor %}
-
- # Don't know how to check for this condition, just wait
- - name: Wait for ONOS to install the apps
- wait_for: timeout=15
-
- - name: Add dependencies to ONOS
- uri:
- url: http://localhost:8181/onos/v1/applications/{{ '{{' }} item {{ '}}' }}/active
- method: POST
- user: karaf
- password: karaf
- with_items:
- {% for dependency in dependencies %}
+ {% endfor %}
+{% endif %}
+
+ # Don't know how to check for this condition, just wait
+ - name: Wait for ONOS to install the apps
+ wait_for: timeout=15
+
+ - name: Add dependencies to ONOS
+ uri:
+ url: http://localhost:8181/onos/v1/applications/{{ '{{' }} item {{ '}}' }}/active
+ method: POST
+ user: karaf
+ password: karaf
+ with_items:
+ {% for dependency in dependencies %}
- {{ dependency }}
- {% endfor %}
-
+ {% endfor %}
diff --git a/xos/observers/vbng/steps/sync_vbngtenant.py b/xos/observers/vbng/steps/sync_vbngtenant.py
index b603ed6..1347e2f 100644
--- a/xos/observers/vbng/steps/sync_vbngtenant.py
+++ b/xos/observers/vbng/steps/sync_vbngtenant.py
@@ -100,11 +100,11 @@
if not vcpe.wan_ip:
self.defer_sync(o, "does not have a WAN IP yet")
- if not vcpe.wan_mac:
- # this should never happen; WAN MAC is computed from WAN IP
- self.defer_sync(o, "does not have a WAN MAC yet")
+ if not vcpe.wan_container_mac:
+ # this should never happen; container MAC is computed from WAN IP
+ self.defer_sync(o, "does not have a WAN container MAC yet")
- return (vcpe.wan_ip, vcpe.wan_mac, vcpe.instance.node.name)
+ return (vcpe.wan_ip, vcpe.wan_container_mac, vcpe.instance.node.name)
def sync_record(self, o):
logger.info("sync'ing VBNGTenant %s" % str(o))
diff --git a/xos/observers/vcpe/steps/sync_vcpetenant.yaml b/xos/observers/vcpe/steps/sync_vcpetenant.yaml
index b485c0f..b5a112a 100644
--- a/xos/observers/vcpe/steps/sync_vcpetenant.yaml
+++ b/xos/observers/vcpe/steps/sync_vcpetenant.yaml
@@ -31,6 +31,8 @@
lan_mac: {{ lan_mac }}
wan_ip: {{ wan_ip }}
wan_mac: {{ wan_mac }}
+ wan_container_mac: {{ wan_container_mac }}
+ wan_next_hop: 10.0.1.253 # FIX ME
private_ip: {{ private_ip }}
private_mac: {{ private_mac }}
hpc_client_ip: {{ hpc_client_ip }}
diff --git a/xos/observers/vcpe/templates/start-vcpe.sh.j2 b/xos/observers/vcpe/templates/start-vcpe.sh.j2
index 7e714de..a3533fa 100755
--- a/xos/observers/vcpe/templates/start-vcpe.sh.j2
+++ b/xos/observers/vcpe/templates/start-vcpe.sh.j2
@@ -5,11 +5,6 @@
ifconfig|grep $MAC| awk '{print $1}'|grep -v '\.'
}
-function generate_mac_from_ip {
- IP=$1
- printf "02:42:%02x:%02x:%02x:%02x\n" `echo $IP|awk -F '.' '{print $1, $2, $3, $4}'`
-}
-
iptables -L > /dev/null
ip6tables -L > /dev/null
@@ -25,9 +20,8 @@
fi
# Set up networking via pipework
-WAN_CONTAINER_MAC=$( generate_mac_from_ip {{ wan_ip }} )
WAN_IFACE=$( mac_to_iface {{ wan_mac }} )
-docker exec $VCPE ifconfig eth0 >> /dev/null || pipework $WAN_IFACE -i eth0 $VCPE {{ wan_ip }}/17@192.168.128.1 $WAN_CONTAINER_MAC
+docker exec $VCPE ifconfig eth0 >> /dev/null || pipework $WAN_IFACE -i eth0 $VCPE {{ wan_ip }}/24@{{ wan_next_hop }} {{ wan_container_mac }}
LAN_IFACE=$( mac_to_iface {{ lan_mac }} )
docker exec $VCPE ifconfig eth1 >> /dev/null || pipework $LAN_IFACE -i eth1 $VCPE 192.168.0.1/24 @{{ vlan_ids[0] }}
diff --git a/xos/observers/vcpe/vcpe_stats_notifier.py b/xos/observers/vcpe/vcpe_stats_notifier.py
index f4bb923..d726e3c 100644
--- a/xos/observers/vcpe/vcpe_stats_notifier.py
+++ b/xos/observers/vcpe/vcpe_stats_notifier.py
@@ -14,7 +14,11 @@
level=logging.INFO
logger=logging.getLogger('vcpe_stats_notifier')
logger.setLevel(level)
+# create formatter
+formatter = logging.Formatter("%(asctime)s;%(levelname)s;%(message)s")
handler=logging.handlers.RotatingFileHandler(logfile,maxBytes=1000000, backupCount=1)
+# add formatter to handler
+handler.setFormatter(formatter)
logger.addHandler(handler)
def extract_dns_stats_from_all_vcpes():
@@ -105,6 +109,9 @@
def publish_cpe_stats():
global producer
global keystone_tenant_id, keystone_user_id, cpe_publisher_id
+
+ logger.debug('publish_cpe_stats invoked')
+
cpe_container_stats = extract_dns_stats_from_all_vcpes()
for k,v in cpe_container_stats.iteritems():
@@ -119,6 +126,8 @@
}
}
producer.publish(msg)
+ logger.debug('Publishing vcpe event: %s', msg)
+
if 'cache_size' in v:
msg = {'event_type': 'vcpe.dns.cache.size',
'message_id':six.text_type(uuid.uuid4()),
@@ -132,6 +141,8 @@
}
}
producer.publish(msg)
+ logger.debug('Publishing vcpe.dns.cache.size event: %s', msg)
+
if 'total_inserted_entries' in v:
msg = {'event_type': 'vcpe.dns.total_inserted_entries',
'message_id':six.text_type(uuid.uuid4()),
@@ -145,6 +156,8 @@
}
}
producer.publish(msg)
+ logger.debug('Publishing vcpe.dns.total_inserted_entries event: %s', msg)
+
if 'replaced_unexpired_entries' in v:
msg = {'event_type': 'vcpe.dns.replaced_unexpired_entries',
'message_id':six.text_type(uuid.uuid4()),
@@ -158,6 +171,7 @@
}
}
producer.publish(msg)
+ logger.debug('Publishing vcpe.dns.replaced_unexpired_entries event: %s', msg)
if 'queries_forwarded' in v:
msg = {'event_type': 'vcpe.dns.queries_forwarded',
@@ -172,6 +186,7 @@
}
}
producer.publish(msg)
+ logger.debug('Publishing vcpe.dns.queries_forwarded event: %s', msg)
if 'queries_answered_locally' in v:
msg = {'event_type': 'vcpe.dns.queries_answered_locally',
@@ -186,6 +201,7 @@
}
}
producer.publish(msg)
+ logger.debug('Publishing vcpe.dns.queries_answered_locally event: %s', msg)
if 'server_stats' in v:
for server in v['server_stats']:
@@ -202,6 +218,7 @@
}
}
producer.publish(msg)
+ logger.debug('Publishing vcpe.dns.server.queries_sent event: %s', msg)
msg = {'event_type': 'vcpe.dns.server.queries_failed',
'message_id':six.text_type(uuid.uuid4()),
@@ -216,6 +233,7 @@
}
}
producer.publish(msg)
+ logger.debug('Publishing vcpe.dns.server.queries_failed event: %s', msg)
def periodic_publish():
publish_cpe_stats()
diff --git a/xos/openstack_observer/ansible.py b/xos/openstack_observer/ansible.py
index ee110c9..94b09bd 100644
--- a/xos/openstack_observer/ansible.py
+++ b/xos/openstack_observer/ansible.py
@@ -144,16 +144,21 @@
return ok_results
def run_template_ssh(name, opts, path='', expected_num=None):
- instance_id = opts["instance_id"]
instance_name = opts["instance_name"]
hostname = opts["hostname"]
private_key = opts["private_key"]
- nat_ip = opts["nat_ip"]
-
- try:
- proxy_ssh = Config().observer_proxy_ssh
- except:
- proxy_ssh = True
+ baremetal_ssh = opts.get("baremetal_ssh",False)
+ if baremetal_ssh:
+ # no instance_id or nat_ip for baremetal
+ # we never proxy to baremetal
+ proxy_ssh = False
+ else:
+ instance_id = opts["instance_id"]
+ nat_ip = opts["nat_ip"]
+ try:
+ proxy_ssh = Config().observer_proxy_ssh
+ except:
+ proxy_ssh = True
(opts, fqp) = get_playbook_fn(opts, path)
private_key_pathname = fqp + ".key"
@@ -177,7 +182,7 @@
f = open(hosts_pathname, "w")
f.write("[%s]\n" % instance_name)
- if proxy_ssh:
+ if proxy_ssh or baremetal_ssh:
f.write("%s ansible_ssh_private_key_file=%s\n" % (hostname, private_key_pathname))
else:
# acb: Login user is hardcoded, this is not great
diff --git a/xos/openstack_observer/steps/sync_container.py b/xos/openstack_observer/steps/sync_container.py
new file mode 100644
index 0000000..de4a2ce
--- /dev/null
+++ b/xos/openstack_observer/steps/sync_container.py
@@ -0,0 +1,122 @@
+import hashlib
+import os
+import socket
+import sys
+import base64
+import time
+from django.db.models import F, Q
+from xos.config import Config
+from observer.syncstep import SyncStep
+from observer.ansible import run_template_ssh
+from core.models import Service, Slice, Container
+from services.onos.models import ONOSService, ONOSApp
+from util.logger import Logger, logging
+
+# hpclibrary will be in steps/..
+parentdir = os.path.join(os.path.dirname(__file__),"..")
+sys.path.insert(0,parentdir)
+
+logger = Logger(level=logging.INFO)
+
+class SyncContainer(SyncStep):
+ provides=[Container]
+ observes=Container
+ requested_interval=0
+ template_name = "sync_container.yaml"
+
+ def __init__(self, *args, **kwargs):
+ super(SyncContainer, self).__init__(*args, **kwargs)
+
+# def fetch_pending(self, deleted):
+# if (not deleted):
+# objs = ONOSService.get_service_objects().filter(Q(enacted__lt=F('updated')) | Q(enacted=None),Q(lazy_blocked=False))
+# else:
+# objs = ONOSService.get_deleted_service_objects()
+#
+# return objs
+
+ def get_node(self,o):
+ return o.node
+
+ def get_node_key(self, node):
+ return "/root/setup/node_key"
+ #return "/opt/xos/node-key"
+
+ def get_instance_port(self, container_port):
+ print container_port
+ print container_port.network
+ for p in container_port.network.links.all():
+ if (p.instance) and (p.instance.node == container_port.container.node) and (p.mac):
+ return p
+ return None
+
+ def get_ports(self, o):
+ i=0
+ ports = []
+ for port in o.ports.all():
+ if not port.mac:
+ raise Exception("Port on network %s is not yet ready" % port.network.name)
+
+ pd={}
+ pd["device"] = "eth%d" % i
+ pd["mac"] = port.mac
+ pd["ip"] = port.ip
+
+ instance_port = self.get_instance_port(port)
+ if not instance_port:
+ raise Exception("No instance on slice for port on network %s" % port.network.name)
+
+ pd["snoop_instance_mac"] = instance_port.mac
+ pd["snoop_instance_id"] = instance_port.instance.instance_id
+
+ ports.append(pd)
+ return ports
+
+ def get_extra_attributes(self, o):
+ fields={}
+ fields["ansible_tag"] = "container-%s" % str(o.id)
+ fields["baremetal_ssh"] = True
+ fields["instance_name"] = "rootcontext"
+ fields["container_name"] = "%s-%s" % (o.slice.name, str(o.id))
+ fields["docker_image"] = o.docker_image
+ fields["username"] = "root"
+ fields["ports"] = self.get_ports(o)
+ return fields
+
+ def sync_fields(self, o, fields):
+ self.run_playbook(o, fields)
+
+ def sync_record(self, o):
+ logger.info("sync'ing object %s" % str(o))
+
+ node = self.get_node(o)
+ node_key_name = self.get_node_key(node)
+
+ if not os.path.exists(node_key_name):
+ raise Exception("Node key %s does not exist" % node_key_name)
+
+ node_key = file(node_key_name).read()
+
+ fields = { "hostname": node.name,
+ "private_key": node_key,
+ }
+
+ # If 'o' defines a 'sync_attributes' list, then we'll copy those
+ # attributes into the Ansible recipe's field list automatically.
+ if hasattr(o, "sync_attributes"):
+ for attribute_name in o.sync_attributes:
+ fields[attribute_name] = getattr(o, attribute_name)
+
+ fields.update(self.get_extra_attributes(o))
+
+ self.sync_fields(o, fields)
+
+ o.save()
+
+ def run_playbook(self, o, fields):
+ tStart = time.time()
+ run_template_ssh(self.template_name, fields, path="container")
+ logger.info("playbook execution time %d" % int(time.time()-tStart))
+
+ def delete_record(self, m):
+ pass
diff --git a/xos/openstack_observer/steps/sync_container.yaml b/xos/openstack_observer/steps/sync_container.yaml
new file mode 100644
index 0000000..a707d0b
--- /dev/null
+++ b/xos/openstack_observer/steps/sync_container.yaml
@@ -0,0 +1,91 @@
+---
+- hosts: {{ instance_name }}
+ gather_facts: False
+ connection: ssh
+ user: {{ username }}
+ sudo: yes
+
+ vars:
+ container_name: {{ container_name }}
+ docker_image: {{ docker_image }}
+ ports:
+ {% for port in ports %}
+ - device: {{ port.device }}
+ mac: {{ port.mac }}
+ ip: {{ port.ip }}
+ snoop_instance_mac: {{ port.snoop_instance_mac }}
+ snoop_instance_id: {{ port.snoop_instance_id }}
+ {% endfor %}
+
+ tasks:
+
+# - name: Fix /etc/hosts
+# lineinfile:
+# dest=/etc/hosts
+# regexp="127.0.0.1 localhost"
+# line="127.0.0.1 localhost {{ instance_hostname }}"
+
+ - name: Add repo key
+ apt_key:
+ keyserver=hkp://pgp.mit.edu:80
+ id=58118E89F3A912897C070ADBF76221572C52609D
+
+ - name: Install Docker repo
+ apt_repository:
+ repo="deb https://apt.dockerproject.org/repo ubuntu-trusty main"
+ state=present
+
+ - name: Install Docker
+ apt:
+ name={{ '{{' }} item {{ '}}' }}
+ state=latest
+ update_cache=yes
+ with_items:
+ - docker-engine
+ - python-pip
+ - python-httplib2
+
+ # Something is installing a requests library that is incompative with pip, and
+ # will cause this recipe to fail next time it tries to run pip. Only the one
+ # in /usr/local/lib is bad. There's still a good one in /usr/lib
+ - name: check if bad requests library installed
+ stat: path=/usr/local/lib/python2.7/dist-packages/requests
+ register: bad_requests
+
+ - name: remove bad request library
+ shell: mv /usr/local/lib/python2.7/dist-packages/requests /usr/local/lib/python2.7/dist-packages/requests-bad
+ when: bad_requests.stat.exists == True
+
+ - name: Install docker-py
+ pip:
+ name=docker-py
+ state=latest
+
+ - name: install Pipework
+ get_url: url=https://raw.githubusercontent.com/jpetazzo/pipework/master/pipework
+ dest=/usr/local/bin/pipework
+ mode=0755
+
+# - name: Start Container
+# docker:
+# docker_api_version: "1.18"
+# name: {{ container_name }}
+# # was: reloaded
+# state: running
+# image: {{ docker_image }}
+
+ - name: container upstart
+ template: src=/opt/xos/openstack_observer/templates/container.conf.j2 dest=/etc/init/container-{{ container_name }}.conf
+
+ - name: container systemd
+ template: src=/opt/xos/openstack_observer/templates/container.service.j2 dest=/lib/systemd/system/container-{{ container_name }}.service
+
+ - name: container startup script
+ template: src=/opt/xos/openstack_observer/templates/start-container.sh.j2 dest=/usr/local/sbin/start-container-{{ container_name }}.sh mode=0755
+
+ - name: restart systemd
+ shell: systemctl daemon-reload
+
+ - name: Make sure container is running
+ service: name=container-{{ container_name }} state=started
+
diff --git a/xos/openstack_observer/steps/sync_ports.py b/xos/openstack_observer/steps/sync_ports.py
index 967bef9..7b20d29 100644
--- a/xos/openstack_observer/steps/sync_ports.py
+++ b/xos/openstack_observer/steps/sync_ports.py
@@ -144,9 +144,14 @@
# For ports that were created by the user, find that ones
# that don't have neutron ports, and create them.
- for port in Port.objects.filter(port_id__isnull=True, instance__isnull=False):
- #logger.info("XXX working on port %s" % port)
- controller = port.instance.node.site_deployment.controller
+ for port in Port.objects.filter(Q(port_id__isnull=True), Q(instance__isnull=False) | Q(container__isnull=False)):
+ logger.info("XXX working on port %s" % port)
+ if port.instance:
+ controller = port.instance.node.site_deployment.controller
+ slice = port.instance.slice
+ else:
+ controller = port.container.node.site_deployment.controller
+ slice = port.container.slice
if controller:
cn=port.network.controllernetworks.filter(controller=controller)
if not cn:
@@ -174,7 +179,7 @@
caller = port.network.owner.creator
auth = {'username': caller.email,
'password': caller.remote_password,
- 'tenant': port.instance.slice.name} # port.network.owner.name}
+ 'tenant': slice.name}
client = OpenStackClient(controller=controller, **auth) # cacert=self.config.nova_ca_ssl_cert,
driver = OpenStackDriver(client=client)
@@ -183,6 +188,10 @@
if neutron_port["fixed_ips"]:
port.ip = neutron_port["fixed_ips"][0]["ip_address"]
port.mac = neutron_port["mac_address"]
+
+ neutron_network = driver.shell.quantum.list_networks(cn.net_id)["networks"][0]
+ if "provider:segmentation_id" in neutron_network:
+ port.segmentation_id = neutron_network["provider:segmentation_id"]
except:
logger.log_exc("failed to create neutron port for %s" % port)
continue
diff --git a/xos/openstack_observer/templates/container.conf.j2 b/xos/openstack_observer/templates/container.conf.j2
new file mode 100644
index 0000000..d3ef42d
--- /dev/null
+++ b/xos/openstack_observer/templates/container.conf.j2
@@ -0,0 +1,11 @@
+# Upstart script for container
+description "container"
+author "smbaker@gmail.com"
+start on filesystem and started docker
+stop on runlevel [!2345]
+respawn
+
+script
+ /usr/local/sbin/start-container-{{ container_name }}.sh
+end script
+
diff --git a/xos/openstack_observer/templates/container.service.j2 b/xos/openstack_observer/templates/container.service.j2
new file mode 100644
index 0000000..9e2b83c
--- /dev/null
+++ b/xos/openstack_observer/templates/container.service.j2
@@ -0,0 +1,9 @@
+[Unit]
+Description={{ container_name }}
+After=docker.service
+
+[Service]
+ExecStart=/bin/bash -c "/usr/local/sbin/start-container-{{ container_name }}.sh"
+
+[Install]
+WantedBy=multi-user.target
diff --git a/xos/openstack_observer/templates/start-container.sh.j2 b/xos/openstack_observer/templates/start-container.sh.j2
new file mode 100644
index 0000000..5656992
--- /dev/null
+++ b/xos/openstack_observer/templates/start-container.sh.j2
@@ -0,0 +1,44 @@
+#!/bin/bash
+
+iptables -L > /dev/null
+ip6tables -L > /dev/null
+
+CONTAINER={{ container_name }}
+IMAGE={{ docker_image }}
+
+docker inspect $CONTAINER > /dev/null 2>&1
+if [ "$?" == 1 ]
+then
+ docker pull $IMAGE
+ docker run -d --name=$CONTAINER --privileged=true --net=none $IMAGE
+else
+ docker start $CONTAINER
+fi
+
+{% if ports %}
+{% for port in ports %}
+IP="{{ port.ip }}"
+MAC="{{ port.mac }}"
+DEVICE="{{ port.device }}"
+INSTANCE_MAC="{{ port.snoop_instance_mac }}"
+INSTANCE_ID="{{ port.snoop_instance_id }}"
+INSTANCE_TAP=`virsh domiflist $INSTANCE_ID | grep -i $INSTANCE_MAC | awk '{print $1}'`
+INSTANCE_TAP=${INSTANCE_TAP:3}
+VLAN_ID=`ovs-vsctl show | grep -i -A 1 port.*$INSTANCE_TAP | grep -i tag | awk '{print $2}'`
+TAP="con`echo $CONTAINER_$DEVICE|md5sum|awk '{print $1}'`"
+TAP=${TAP:0:12}
+echo im=$INSTANCE_MAC ii=$INSTANCE_ID it=$INSTANCE_TAP vlan=$VLAN_ID tap=$TAP con=$CONTAINER dev=$DEVICE mac=$MAC
+ovs-vsctl show | grep -i $TAP
+if [[ $? == 1 ]]; then
+ echo creating tap
+ ovs-vsctl add-port br-int $TAP tag=$VLAN_ID -- set interface $TAP type=internal
+else
+ echo tap exists
+fi
+
+docker exec $CONTAINER ifconfig $DEVICE >> /dev/null || pipework $TAP -i $DEVICE $CONTAINER $IP/24 $MAC
+{% endfor %}
+{% endif %}
+
+# Attach to container
+# docker start -a $CONTAINER
diff --git a/xos/scripts/opencloud b/xos/scripts/opencloud
index b936ce3..189a673 100755
--- a/xos/scripts/opencloud
+++ b/xos/scripts/opencloud
@@ -136,11 +136,8 @@
fi
}
-function remigrate {
- if db_exists; then
- dropdb
- fi
- rm -rf /opt/xos/*/migrations
+function makemigrations {
+ rm -rf /opt/xos/*/migrations /opt/xos/services/*/migrations
python ./manage.py makemigrations core
python ./manage.py makemigrations hpc
python ./manage.py makemigrations requestrouter
@@ -151,6 +148,13 @@
#python ./manage.py makemigrations servcomp
}
+function remigrate {
+ if db_exists; then
+ dropdb
+ fi
+ makemigrations
+}
+
COMMAND=$1
if [ "$COMMAND" = "initdb" ]; then
@@ -226,3 +230,7 @@
createdb
syncdb
fi
+if [ "$COMMAND" = "makemigrations" ]; then
+ makemigrations
+ syncdb
+fi
diff --git a/xos/templates/admin/base.html b/xos/templates/admin/base.html
index d29456a..a7cc0c4 100644
--- a/xos/templates/admin/base.html
+++ b/xos/templates/admin/base.html
@@ -6,6 +6,7 @@
<link rel="stylesheet" type="text/css" href="{% static 'suit/bootstrap/css/bootstrap.min.css' %}" media="all"/>
<link rel="stylesheet" type="text/css" href="{% static 'suit/css/suit.css' %}" media="all">
<link rel="stylesheet" type="text/css" href="{% static 'xos.css' %}" media="all">
+ <link rel="stylesheet" type="text/css" href="{% static 'cord.css' %}" media="all">
{% if XOS_BRANDING_CSS %}
<link rel="stylesheet" type="text/css" href="{{ XOS_BRANDING_CSS }}">
{% endif %}
@@ -43,7 +44,7 @@
<div id="container">
{% block logo %}
- <a href="{% url 'admin:index' %}"><h1 id="site-name"><img class="logo" height="70" width="259" src="{% static 'open-cloud-login-themed-light.png' %}"/></h1></a>
+ <a href="{% url 'admin:index' %}"><h1 id="site-name"><img class="logo" height="70" width="259" src="{% static 'cord_logo_3.png' %}"/></h1></a>
{% endblock %}
{% block header %}
{% if not is_popup %}
diff --git a/xos/templates/admin/dashboard/customize.html b/xos/templates/admin/dashboard/customize.html
index d2e8a20..eb92b21 100644
--- a/xos/templates/admin/dashboard/customize.html
+++ b/xos/templates/admin/dashboard/customize.html
@@ -1,39 +1,50 @@
-<form>
+<div class="row-fluid">
+ <div class="span12 text-right">
+ <a href="core/dashboardview/add/" class="btn btn-success">
+ <i class="icon icon-plus"></i> Add
+ </a>
+ </div>
+</div>
+<form>
<div class="customize_row">
- <div class="customize_column">
- <div>Available Dashboard Views</div>
- <select name="selectfrom" id="select-from" multiple size="5">
- {% for cp in unusedDashboards %}
- <option value="{{ cp }}">{{ cp }}</option>
- {% endfor %}
- </select>
- </div>
- <div class="customize_column">
- <br>
- <div class="btn btn-success" id="customize-btn-add">Add »</div><br><br>
- <div class="btn btn-success" id="customize-btn-remove">« Remove</div>
- </div>
- <div class="customize_column">
- <div>Selected Dashboard Views</div>
- <select name="selectto" id="select-to" multiple size="5">
- {% for cp in dashboards %}
- <option value="{{ cp }}">{{ cp }}</option>
- {% endfor %}
- </select>
- <br>
- <div class="btn btn-high btn-info" id="customize-btn-save">Save</div>
- <div style="display: none" id="customize-msg-saving">Saving...</div>
- </div>
- <div class="customize_column">
- <br>
- <div class="btn btn-success" id="customize-btn-up">Up</div><br><br>
- <div class="btn btn-success" id="customize-btn-down">Down</div>
- </div>
+ <div class="customize_column">
+ <div>Available Dashboard Views</div>
+ <select name="selectfrom" id="select-from" multiple size="5">
+ {% for cp in unusedDashboards %}
+ <option value="{{ cp }}">{{ cp }}</option>
+ {% endfor %}
+ </select>
+ </div>
+ <div class="customize_column">
+ <br>
+ <div class="btn btn-success" id="customize-btn-add">Add »</div>
+ <br>
+ <br>
+ <div class="btn btn-success" id="customize-btn-remove">« Remove</div>
+ </div>
+ <div class="customize_column">
+ <div>Selected Dashboard Views</div>
+ <select name="selectto" id="select-to" multiple size="5">
+ {% for cp in dashboards %}
+ <option value="{{ cp }}">{{ cp }}</option>
+ {% endfor %}
+ </select>
+ <br>
+ <div class="btn btn-high btn-info" id="customize-btn-save">Save</div>
+ <div style="display: none" id="customize-msg-saving">Saving...</div>
+ </div>
+ <div class="customize_column">
+ <br>
+ <div class="btn btn-success" id="customize-btn-up">Up</div>
+ <br>
+ <br>
+ <div class="btn btn-success" id="customize-btn-down">Down</div>
+ </div>
</div>
</form>
-
-<script>
-$(document).ready(function() {
+
+<script>
+$(document).ready(function() {
$('#customize-btn-add').click(function(){
$('#select-from option:selected').each( function() {
$('#select-to').append("<option value='"+$(this).val()+"'>"+$(this).text()+"</option>");
@@ -71,23 +82,22 @@
var items=[];
$("#select-to option").each(function() { items.push($(this).val()); });
$.ajax({
- url: '/customize/',
- dataType: 'json',
- data: {
- dashboards: items.join(","),
- csrfmiddlewaretoken: "{{ csrf_token }}" // < here
- },
- type: 'POST',
- error: function (jqXHR, textStatus, errorThrown) {
- errorDialog("Error", textStatus + " " + jqXHR.responseText);
- $("#customize-btn-save").show();
- $("#customize-msg-saving").hide();
- },
- success: function () {
- location.reload();
- }
+ url: '/customize/',
+ dataType: 'json',
+ data: {
+ dashboards: items.join(","),
+ csrfmiddlewaretoken: "{{ csrf_token }}" // < here
+ },
+ type: 'POST',
+ error: function (jqXHR, textStatus, errorThrown) {
+ errorDialog("Error", textStatus + " " + jqXHR.responseText);
+ $("#customize-btn-save").show();
+ $("#customize-msg-saving").hide();
+ },
+ success: function () {
+ location.reload();
+ }
});
- });
-});
-</script>
-
+ });
+});
+</script>
\ No newline at end of file
diff --git a/xos/tosca/custom_types/xos.m4 b/xos/tosca/custom_types/xos.m4
index 055817d..a661af7 100644
--- a/xos/tosca/custom_types/xos.m4
+++ b/xos/tosca/custom_types/xos.m4
@@ -120,6 +120,9 @@
config_addresses.json:
type: string
required: false
+ config_network-cfg.json:
+ type: string
+ required: false
config_virtualbng.json:
type: string
required: false
@@ -488,6 +491,18 @@
type: string
required: false
description: OpenStack domain (or "Default")
+ rabbit_host:
+ type: string
+ required: false
+ description: Rabbit host
+ rabbit_user:
+ type: string
+ required: false
+ description: Rabbit user
+ rabbit_password:
+ type: string
+ required: false
+ description: Rabbit password
tosca.nodes.Site:
derived_from: tosca.nodes.Root
@@ -559,6 +574,23 @@
node:
type: tosca.capabilities.xos.Node
+ tosca.nodes.DashboardView:
+ derived_from: tosca.nodes.Root
+ description: >
+ An XOS Dashboard View
+ capabilities:
+ dashboardview:
+ type: tosca.capabilities.xos.DashboardView
+ properties:
+ xos_base_props
+ enabled:
+ type: boolean
+ default: true
+ url:
+ type: string
+ required: false
+ description: URL to the dashboard
+
tosca.relationships.MemberOfSlice:
derived_from: tosca.relationships.Root
valid_target_types: [ tosca.capabilities.xos.Slice ]
@@ -639,6 +671,10 @@
derived_from: tosca.relationships.Root
valid_target_types: [ tosca.capabilities.xos.Subscriber ]
+ tosca.relationships.UsesDashboard:
+ derived_from: tosca.relationships.Root
+ valid_target_types: [ tosca.capabilities.xos.DashboardView ]
+
tosca.capabilities.xos.Service:
derived_from: tosca.capabilities.Root
description: An XOS Service
@@ -687,3 +723,6 @@
derived_from: tosca.capabilities.Root
description: An XOS Image
+ tosca.capabilities.xos.DashboardView:
+ derived_from: tosca.capabilities.Root
+ description: An XOS DashboardView
diff --git a/xos/tosca/custom_types/xos.yaml b/xos/tosca/custom_types/xos.yaml
index 409e86b..9170ecf 100644
--- a/xos/tosca/custom_types/xos.yaml
+++ b/xos/tosca/custom_types/xos.yaml
@@ -131,6 +131,9 @@
config_addresses.json:
type: string
required: false
+ config_network-cfg.json:
+ type: string
+ required: false
config_virtualbng.json:
type: string
required: false
@@ -638,6 +641,18 @@
type: string
required: false
description: OpenStack domain (or "Default")
+ rabbit_host:
+ type: string
+ required: false
+ description: Rabbit host
+ rabbit_user:
+ type: string
+ required: false
+ description: Rabbit user
+ rabbit_password:
+ type: string
+ required: false
+ description: Rabbit password
tosca.nodes.Site:
derived_from: tosca.nodes.Root
@@ -742,6 +757,34 @@
node:
type: tosca.capabilities.xos.Node
+ tosca.nodes.DashboardView:
+ derived_from: tosca.nodes.Root
+ description: >
+ An XOS Dashboard View
+ capabilities:
+ dashboardview:
+ type: tosca.capabilities.xos.DashboardView
+ properties:
+ no-delete:
+ type: boolean
+ default: false
+ description: Do not allow Tosca to delete this object
+ no-create:
+ type: boolean
+ default: false
+ description: Do not allow Tosca to create this object
+ no-update:
+ type: boolean
+ default: false
+ description: Do not allow Tosca to update this object
+ enabled:
+ type: boolean
+ default: true
+ url:
+ type: string
+ required: false
+ description: URL to the dashboard
+
tosca.relationships.MemberOfSlice:
derived_from: tosca.relationships.Root
valid_target_types: [ tosca.capabilities.xos.Slice ]
@@ -822,6 +865,10 @@
derived_from: tosca.relationships.Root
valid_target_types: [ tosca.capabilities.xos.Subscriber ]
+ tosca.relationships.UsesDashboard:
+ derived_from: tosca.relationships.Root
+ valid_target_types: [ tosca.capabilities.xos.DashboardView ]
+
tosca.capabilities.xos.Service:
derived_from: tosca.capabilities.Root
description: An XOS Service
@@ -870,3 +917,6 @@
derived_from: tosca.capabilities.Root
description: An XOS Image
+ tosca.capabilities.xos.DashboardView:
+ derived_from: tosca.capabilities.Root
+ description: An XOS DashboardView
diff --git a/xos/tosca/resources/ceilometertenant.py b/xos/tosca/resources/ceilometertenant.py
new file mode 100644
index 0000000..6599f33
--- /dev/null
+++ b/xos/tosca/resources/ceilometertenant.py
@@ -0,0 +1,39 @@
+import os
+import pdb
+import sys
+import tempfile
+sys.path.append("/opt/tosca")
+from translator.toscalib.tosca_template import ToscaTemplate
+import pdb
+
+from ceilometer.models import MonitoringChannel, CeilometerService
+
+from xosresource import XOSResource
+
+class XOSCeilometerTenant(XOSResource):
+ provides = "tosca.nodes.CeilometerTenant"
+ xos_model = MonitoringChannel
+ name_field = None
+
+ def get_xos_args(self, throw_exception=True):
+ args = super(XOSCeilometerTenant, 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(CeilometerService, 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(XOSCeilometerTenant, self).can_delete(obj)
+
diff --git a/xos/tosca/resources/controller.py b/xos/tosca/resources/controller.py
index 9a20ea5..2aa208c 100644
--- a/xos/tosca/resources/controller.py
+++ b/xos/tosca/resources/controller.py
@@ -15,7 +15,7 @@
class XOSController(XOSResource):
provides = "tosca.nodes.Controller"
xos_model = Controller
- copyin_props = ["backend_type", "version", "auth_url", "admin_user", "admin_password", "admin_tenant", "domain"]
+ copyin_props = ["backend_type", "version", "auth_url", "admin_user", "admin_password", "admin_tenant", "domain", "rabbit_host", "rabbit_user", "rabbit_password"]
def get_xos_args(self):
args = super(XOSController, self).get_xos_args()
diff --git a/xos/tosca/resources/dashboardview.py b/xos/tosca/resources/dashboardview.py
new file mode 100644
index 0000000..9f7687c
--- /dev/null
+++ b/xos/tosca/resources/dashboardview.py
@@ -0,0 +1,23 @@
+import os
+import pdb
+import sys
+import tempfile
+sys.path.append("/opt/tosca")
+from translator.toscalib.tosca_template import ToscaTemplate
+
+from core.models import DashboardView, Site, Deployment, SiteDeployment
+
+from xosresource import XOSResource
+
+class XOSDashboardView(XOSResource):
+ provides = "tosca.nodes.DashboardView"
+ xos_model = DashboardView
+ copyin_props = ["url","enabled"]
+
+ def get_xos_args(self):
+ return super(XOSDashboardView, self).get_xos_args()
+
+ def can_delete(self, obj):
+ return super(XOSDashboardView, self).can_delete(obj)
+
+
diff --git a/xos/tosca/resources/user.py b/xos/tosca/resources/user.py
index 53323c5..724bc3d 100644
--- a/xos/tosca/resources/user.py
+++ b/xos/tosca/resources/user.py
@@ -5,7 +5,7 @@
sys.path.append("/opt/tosca")
from translator.toscalib.tosca_template import ToscaTemplate
-from core.models import User, Site, SiteRole, SliceRole, SlicePrivilege, SitePrivilege
+from core.models import User, Site, SiteRole, SliceRole, SlicePrivilege, SitePrivilege, DashboardView, UserDashboardView
from xosresource import XOSResource
@@ -46,6 +46,21 @@
sp.save()
self.info("Added site privilege on %s role %s for %s" % (str(dest), str(role), str(obj)))
+ dashboard_order = 10
+ for reqs in self.nodetemplate.requirements:
+ for (k,v) in reqs.items():
+ if (v["relationship"] == "tosca.relationships.UsesDashboard"):
+ dashboard_name = v["node"]
+ dashboard = self.get_xos_object(DashboardView, name=dashboard_name)
+
+ udvs = UserDashboardView.objects.filter(user=obj, dashboardView=dashboard)
+ if not udvs:
+ self.info("Adding UserDashboardView from %s to %s" % (obj, dashboard))
+
+ udv = UserDashboardView(user=obj, dashboardView=dashboard, order=dashboard_order)
+ dashboard_order += 10
+ udv.save()
+
def create(self):
nodetemplate = self.nodetemplate
diff --git a/xos/tosca/samples/dashboardview.yaml b/xos/tosca/samples/dashboardview.yaml
new file mode 100644
index 0000000..2a358f2
--- /dev/null
+++ b/xos/tosca/samples/dashboardview.yaml
@@ -0,0 +1,34 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: Dashboard View
+
+imports:
+ - custom_types/xos.yaml
+
+topology_template:
+ node_templates:
+ Ceilometer:
+ type: tosca.nodes.DashboardView
+ properties:
+ url: http:/xosmetering/
+
+ Tenant:
+ type: tosca.nodes.DashboardView
+ properties:
+ no-create: true
+ no-update: true
+ no-delete: true
+
+ padmin@vicci.org:
+ type: tosca.nodes.User
+ properties:
+ firstname: XOS
+ lastname: admin
+ is_admin: true
+ requirements:
+ - tenant_dashboard:
+ node: Tenant
+ relationship: tosca.relationships.UsesDashboard
+ - ceilometer_dashboard:
+ node: Ceilometer
+ relationship: tosca.relationships.UsesDashboard
diff --git a/xos/tosca/samples/new_site_deploy_slice.yaml b/xos/tosca/samples/new_site_deploy_slice.yaml
index 6ccadc1..5e36bcb 100644
--- a/xos/tosca/samples/new_site_deploy_slice.yaml
+++ b/xos/tosca/samples/new_site_deploy_slice.yaml
@@ -27,6 +27,9 @@
admin_password: letmeout
admin_tenant: 12345678
domain: mydomain
+ rabbit_host: rabhost
+ rabbit_user: rabuser
+ rabbit_password: rabpw
newsite:
type: tosca.nodes.Site
diff --git a/xos/uwsgi/xos.ini b/xos/uwsgi/xos.ini
index da7f7dd..63eb6b2 100644
--- a/xos/uwsgi/xos.ini
+++ b/xos/uwsgi/xos.ini
@@ -2,17 +2,17 @@
chdir = /opt/xos
module = xos.wsgi:application
env = DJANGO_SETTINGS_MODULE=xos.settings
-socket = /var/run/uwsgi/xos.sock
+socket = /var/run/uwsgi.xos.sock
socket = 127.0.0.1:9001
-http = 128.112.139.48:9002
+http = 127.0.0.1:9002
stats = 127.0.0.1:9003
workers = 3
master = true
processes = 8
-uid = uwsgi
-gid = webserver
+uid = root
+gid = root
harakiri = 20
-daemonize=/var/log/uwsgi/xos.log
+daemonize=/var/log/uwsgi.xos.log
static-map = /static=/var/www/xos/static
-pidfile = /var/run/uwsgi/uwsgi.pid
+pidfile = /var/run/uwsgi.xos.pid
buffer-size = 8192
diff --git a/xos/xos/hpcapi.py b/xos/xos/hpcapi.py
index 389238e..9de4989 100644
--- a/xos/xos/hpcapi.py
+++ b/xos/xos/hpcapi.py
@@ -38,9 +38,6 @@
return patterns('',
url(r'^hpcapi/$', hpc_api_root),
- url(r'hpcapi/services/$', ServiceList.as_view(), name='service-list'),
- url(r'hpcapi/services/(?P<pk>[a-zA-Z0-9\-]+)/$', ServiceDetail.as_view(), name ='service-detail'),
-
url(r'hpcapi/hpchealthchecks/$', HpcHealthCheckList.as_view(), name='hpchealthcheck-list'),
url(r'hpcapi/hpchealthchecks/(?P<pk>[a-zA-Z0-9\-]+)/$', HpcHealthCheckDetail.as_view(), name ='hpchealthcheck-detail'),
@@ -53,9 +50,6 @@
url(r'hpcapi/cdnprefixs/$', CDNPrefixList.as_view(), name='cdnprefix-list'),
url(r'hpcapi/cdnprefixs/(?P<pk>[a-zA-Z0-9\-]+)/$', CDNPrefixDetail.as_view(), name ='cdnprefix-detail'),
- url(r'hpcapi/users/$', UserList.as_view(), name='user-list'),
- url(r'hpcapi/users/(?P<pk>[a-zA-Z0-9\-]+)/$', UserDetail.as_view(), name ='user-detail'),
-
url(r'hpcapi/serviceproviders/$', ServiceProviderList.as_view(), name='serviceprovider-list'),
url(r'hpcapi/serviceproviders/(?P<pk>[a-zA-Z0-9\-]+)/$', ServiceProviderDetail.as_view(), name ='serviceprovider-detail'),
@@ -73,12 +67,10 @@
@api_view(['GET'])
def hpc_api_root(request, format=None):
return Response({
- 'services': reverse('service-list', request=request, format=format),
'hpchealthchecks': reverse('hpchealthcheck-list', request=request, format=format),
'hpcservices': reverse('hpcservice-list', request=request, format=format),
'originservers': reverse('originserver-list', request=request, format=format),
'cdnprefixs': reverse('cdnprefix-list', request=request, format=format),
- 'users': reverse('user-list', request=request, format=format),
'serviceproviders': reverse('serviceprovider-list', request=request, format=format),
'contentproviders': reverse('contentprovider-list', request=request, format=format),
'accessmaps': reverse('accessmap-list', request=request, format=format),
@@ -142,41 +134,6 @@
-class ServiceSerializer(serializers.HyperlinkedModelSerializer):
- id = IdField()
-
- humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
- validators = serializers.SerializerMethodField("getValidators")
- def getHumanReadableName(self, obj):
- return str(obj)
- def getValidators(self, obj):
- try:
- return obj.getValidators()
- except:
- return None
- class Meta:
- model = Service
- fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','policed','backend_register','backend_status','deleted','write_protect','lazy_blocked','no_sync','description','enabled','kind','name','versionNumber','published','view_url','icon_url','public_key','service_specific_id','service_specific_attribute',)
-
-class ServiceIdSerializer(XOSModelSerializer):
- id = IdField()
-
- humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
- validators = serializers.SerializerMethodField("getValidators")
- def getHumanReadableName(self, obj):
- return str(obj)
- def getValidators(self, obj):
- try:
- return obj.getValidators()
- except:
- return None
- class Meta:
- model = Service
- fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','policed','backend_register','backend_status','deleted','write_protect','lazy_blocked','no_sync','description','enabled','kind','name','versionNumber','published','view_url','icon_url','public_key','service_specific_id','service_specific_attribute',)
-
-
-
-
class HpcHealthCheckSerializer(serializers.HyperlinkedModelSerializer):
id = IdField()
@@ -226,7 +183,7 @@
return None
class Meta:
model = HpcService
- fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','policed','backend_register','backend_status','deleted','write_protect','lazy_blocked','no_sync','description','enabled','kind','name','versionNumber','published','view_url','icon_url','public_key','service_specific_id','service_specific_attribute','service_ptr','cmi_hostname','hpc_port80','watcher_hpc_network','watcher_dnsdemux_network','watcher_dnsredir_network',)
+ fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','policed','backend_register','backend_status','deleted','write_protect','lazy_blocked','no_sync','description','enabled','kind','name','versionNumber','published','view_url','icon_url','public_key','service_specific_id','service_specific_attribute','cmi_hostname','hpc_port80','watcher_hpc_network','watcher_dnsdemux_network','watcher_dnsredir_network',)
class HpcServiceIdSerializer(XOSModelSerializer):
id = IdField()
@@ -242,7 +199,7 @@
return None
class Meta:
model = HpcService
- fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','policed','backend_register','backend_status','deleted','write_protect','lazy_blocked','no_sync','description','enabled','kind','name','versionNumber','published','view_url','icon_url','public_key','service_specific_id','service_specific_attribute','service_ptr','cmi_hostname','hpc_port80','watcher_hpc_network','watcher_dnsdemux_network','watcher_dnsredir_network',)
+ fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','policed','backend_register','backend_status','deleted','write_protect','lazy_blocked','no_sync','description','enabled','kind','name','versionNumber','published','view_url','icon_url','public_key','service_specific_id','service_specific_attribute','cmi_hostname','hpc_port80','watcher_hpc_network','watcher_dnsdemux_network','watcher_dnsredir_network',)
@@ -317,49 +274,6 @@
-class UserSerializer(serializers.HyperlinkedModelSerializer):
- id = IdField()
-
-
- contentproviders = serializers.HyperlinkedRelatedField(many=True, read_only=True, view_name='contentprovider-detail')
-
-
- humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
- validators = serializers.SerializerMethodField("getValidators")
- def getHumanReadableName(self, obj):
- return str(obj)
- def getValidators(self, obj):
- try:
- return obj.getValidators()
- except:
- return None
- class Meta:
- model = User
- fields = ('humanReadableName', 'validators', 'id','password','last_login','email','username','firstname','lastname','phone','user_url','site','public_key','is_active','is_admin','is_staff','is_readonly','is_registering','is_appuser','login_page','created','updated','enacted','policed','backend_status','deleted','write_protect','timezone','contentproviders',)
-
-class UserIdSerializer(XOSModelSerializer):
- id = IdField()
-
-
- contentproviders = serializers.PrimaryKeyRelatedField(many=True, queryset = ContentProvider.objects.all())
-
-
- humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
- validators = serializers.SerializerMethodField("getValidators")
- def getHumanReadableName(self, obj):
- return str(obj)
- def getValidators(self, obj):
- try:
- return obj.getValidators()
- except:
- return None
- class Meta:
- model = User
- fields = ('humanReadableName', 'validators', 'id','password','last_login','email','username','firstname','lastname','phone','user_url','site','public_key','is_active','is_admin','is_staff','is_readonly','is_registering','is_appuser','login_page','created','updated','enacted','policed','backend_status','deleted','write_protect','timezone','contentproviders',)
-
-
-
-
class ServiceProviderSerializer(serializers.HyperlinkedModelSerializer):
id = IdField()
@@ -398,21 +312,9 @@
class ContentProviderSerializer(serializers.HyperlinkedModelSerializer):
id = IdField()
- humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
- validators = serializers.SerializerMethodField("getValidators")
- def getHumanReadableName(self, obj):
- return str(obj)
- def getValidators(self, obj):
- try:
- return obj.getValidators()
- except:
- return None
- class Meta:
- model = ContentProvider
- fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','policed','backend_register','backend_status','deleted','write_protect','lazy_blocked','no_sync','content_provider_id','name','enabled','description','serviceProvider',)
-
-class ContentProviderIdSerializer(XOSModelSerializer):
- id = IdField()
+
+ users = serializers.HyperlinkedRelatedField(many=True, read_only=True, view_name='user-detail')
+
humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
validators = serializers.SerializerMethodField("getValidators")
@@ -425,7 +327,27 @@
return None
class Meta:
model = ContentProvider
- fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','policed','backend_register','backend_status','deleted','write_protect','lazy_blocked','no_sync','content_provider_id','name','enabled','description','serviceProvider',)
+ fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','policed','backend_register','backend_status','deleted','write_protect','lazy_blocked','no_sync','content_provider_id','name','enabled','description','serviceProvider','users',)
+
+class ContentProviderIdSerializer(XOSModelSerializer):
+ id = IdField()
+
+
+ users = serializers.PrimaryKeyRelatedField(many=True, queryset = User.objects.all())
+
+
+ humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
+ validators = serializers.SerializerMethodField("getValidators")
+ def getHumanReadableName(self, obj):
+ return str(obj)
+ def getValidators(self, obj):
+ try:
+ return obj.getValidators()
+ except:
+ return None
+ class Meta:
+ model = ContentProvider
+ fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','policed','backend_register','backend_status','deleted','write_protect','lazy_blocked','no_sync','content_provider_id','name','enabled','description','serviceProvider','users',)
@@ -502,8 +424,6 @@
serializerLookUp = {
- Service: ServiceSerializer,
-
HpcHealthCheck: HpcHealthCheckSerializer,
HpcService: HpcServiceSerializer,
@@ -512,8 +432,6 @@
CDNPrefix: CDNPrefixSerializer,
- User: UserSerializer,
-
ServiceProvider: ServiceProviderSerializer,
ContentProvider: ContentProviderSerializer,
@@ -528,53 +446,6 @@
# Based on core/views/*.py
-class ServiceList(XOSListCreateAPIView):
- queryset = Service.objects.select_related().all()
- serializer_class = ServiceSerializer
- id_serializer_class = ServiceIdSerializer
- filter_backends = (filters.DjangoFilterBackend,)
- filter_fields = ('id','created','updated','enacted','policed','backend_register','backend_status','deleted','write_protect','lazy_blocked','no_sync','description','enabled','kind','name','versionNumber','published','view_url','icon_url','public_key','service_specific_id','service_specific_attribute',)
-
- def get_serializer_class(self):
- no_hyperlinks=False
- if hasattr(self.request,"QUERY_PARAMS"):
- no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
- if (no_hyperlinks):
- return self.id_serializer_class
- else:
- return self.serializer_class
-
- def get_queryset(self):
- if (not self.request.user.is_authenticated()):
- raise XOSNotAuthenticated()
- return Service.select_by_user(self.request.user)
-
-
-class ServiceDetail(XOSRetrieveUpdateDestroyAPIView):
- queryset = Service.objects.select_related().all()
- serializer_class = ServiceSerializer
- id_serializer_class = ServiceIdSerializer
-
- def get_serializer_class(self):
- no_hyperlinks=False
- if hasattr(self.request,"QUERY_PARAMS"):
- no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
- if (no_hyperlinks):
- return self.id_serializer_class
- else:
- return self.serializer_class
-
- def get_queryset(self):
- if (not self.request.user.is_authenticated()):
- raise XOSNotAuthenticated()
- return Service.select_by_user(self.request.user)
-
- # update() is handled by XOSRetrieveUpdateDestroyAPIView
-
- # destroy() is handled by XOSRetrieveUpdateDestroyAPIView
-
-
-
class HpcHealthCheckList(XOSListCreateAPIView):
queryset = HpcHealthCheck.objects.select_related().all()
serializer_class = HpcHealthCheckSerializer
@@ -627,7 +498,7 @@
serializer_class = HpcServiceSerializer
id_serializer_class = HpcServiceIdSerializer
filter_backends = (filters.DjangoFilterBackend,)
- filter_fields = ('id','created','updated','enacted','policed','backend_register','backend_status','deleted','write_protect','lazy_blocked','no_sync','description','enabled','kind','name','versionNumber','published','view_url','icon_url','public_key','service_specific_id','service_specific_attribute','service_ptr','cmi_hostname','hpc_port80','watcher_hpc_network','watcher_dnsdemux_network','watcher_dnsredir_network',)
+ filter_fields = ('id','created','updated','enacted','policed','backend_register','backend_status','deleted','write_protect','lazy_blocked','no_sync','description','enabled','kind','name','versionNumber','published','view_url','icon_url','public_key','service_specific_id','service_specific_attribute','cmi_hostname','hpc_port80','watcher_hpc_network','watcher_dnsdemux_network','watcher_dnsredir_network',)
def get_serializer_class(self):
no_hyperlinks=False
@@ -763,53 +634,6 @@
-class UserList(XOSListCreateAPIView):
- queryset = User.objects.select_related().all()
- serializer_class = UserSerializer
- id_serializer_class = UserIdSerializer
- filter_backends = (filters.DjangoFilterBackend,)
- filter_fields = ('id','password','last_login','email','username','firstname','lastname','phone','user_url','site','public_key','is_active','is_admin','is_staff','is_readonly','is_registering','is_appuser','login_page','created','updated','enacted','policed','backend_status','deleted','write_protect','timezone','contentproviders',)
-
- def get_serializer_class(self):
- no_hyperlinks=False
- if hasattr(self.request,"QUERY_PARAMS"):
- no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
- if (no_hyperlinks):
- return self.id_serializer_class
- else:
- return self.serializer_class
-
- def get_queryset(self):
- if (not self.request.user.is_authenticated()):
- raise XOSNotAuthenticated()
- return User.select_by_user(self.request.user)
-
-
-class UserDetail(XOSRetrieveUpdateDestroyAPIView):
- queryset = User.objects.select_related().all()
- serializer_class = UserSerializer
- id_serializer_class = UserIdSerializer
-
- def get_serializer_class(self):
- no_hyperlinks=False
- if hasattr(self.request,"QUERY_PARAMS"):
- no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
- if (no_hyperlinks):
- return self.id_serializer_class
- else:
- return self.serializer_class
-
- def get_queryset(self):
- if (not self.request.user.is_authenticated()):
- raise XOSNotAuthenticated()
- return User.select_by_user(self.request.user)
-
- # update() is handled by XOSRetrieveUpdateDestroyAPIView
-
- # destroy() is handled by XOSRetrieveUpdateDestroyAPIView
-
-
-
class ServiceProviderList(XOSListCreateAPIView):
queryset = ServiceProvider.objects.select_related().all()
serializer_class = ServiceProviderSerializer
@@ -862,7 +686,7 @@
serializer_class = ContentProviderSerializer
id_serializer_class = ContentProviderIdSerializer
filter_backends = (filters.DjangoFilterBackend,)
- filter_fields = ('id','created','updated','enacted','policed','backend_register','backend_status','deleted','write_protect','lazy_blocked','no_sync','content_provider_id','name','enabled','description','serviceProvider',)
+ filter_fields = ('id','created','updated','enacted','policed','backend_register','backend_status','deleted','write_protect','lazy_blocked','no_sync','content_provider_id','name','enabled','description','serviceProvider','users',)
def get_serializer_class(self):
no_hyperlinks=False
diff --git a/xos/xos/settings.py b/xos/xos/settings.py
index e660352..3e64d15 100644
--- a/xos/xos/settings.py
+++ b/xos/xos/settings.py
@@ -120,6 +120,12 @@
# Python dotted path to the WSGI application used by Django's runserver.
WSGI_APPLICATION = 'xos.wsgi.application'
+# Default: 'csrftoken'
+CSRF_COOKIE_NAME = 'xoscsrftoken'
+# Default: 'django_language'
+LANGUAGE_COOKIE_NAME = 'xos_django_language'
+# Default: 'sessionid'
+SESSION_COOKIE_NAME = 'xossessionid'
TEMPLATE_DIRS = (
# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".