diff options
author | Trevor Bramwell <tbramwell@linuxfoundation.org> | 2017-09-22 11:48:38 -0700 |
---|---|---|
committer | Trevor Bramwell <tbramwell@linuxfoundation.org> | 2017-09-22 11:48:38 -0700 |
commit | aeb2791f4d3a5e23090e56c330436205a61629d7 (patch) | |
tree | 7b4918aba2421f2dc8cdac72f134e74acec92bee /tools/pharos-dashboard | |
parent | 783a439ec2bd23ad969ffe7a3c6b7277f7a565c7 (diff) |
Remove 'tools' Directory
All tools (and history) have been moved to the pharos-tools repository:
https://git.opnfv.org/pharos-tools/
Change-Id: I84fa9b6ebd9b27f42d41f2722eb1221ec39a8c94
Signed-off-by: Trevor Bramwell <tbramwell@linuxfoundation.org>
Diffstat (limited to 'tools/pharos-dashboard')
118 files changed, 0 insertions, 5171 deletions
diff --git a/tools/pharos-dashboard/.gitignore b/tools/pharos-dashboard/.gitignore deleted file mode 100644 index 4154fdd3..00000000 --- a/tools/pharos-dashboard/.gitignore +++ /dev/null @@ -1,46 +0,0 @@ -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] - -# C extensions -*.so - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -.tox/ -.coverage -.cache -nosetests.xml -coverage.xml - -# Django: -*.log -*.pot - -# Celery -celerybeat-schedule.db - -# KDE: -.directory - -# Pycharm: -.idea/ - -# Virtualenv: -venv/ - -# Vim: -*.swp - -# Bower Components: -bower_components/ - -# Production settings -config.env - -# rsa key files -rsa.pem -rsa.pub diff --git a/tools/pharos-dashboard/Makefile b/tools/pharos-dashboard/Makefile deleted file mode 100644 index 90709171..00000000 --- a/tools/pharos-dashboard/Makefile +++ /dev/null @@ -1,38 +0,0 @@ -build: - docker-compose build - -up: - docker-compose up -d - -start: - docker-compose start - -stop: - docker-compose stop - -data: - docker volume create --name=pharos-data - -shell-nginx: - docker exec -ti ng01 bash - -shell-web: - docker exec -ti dg01 bash - -shell-db: - docker exec -ti ps01 bash - -log-nginx: - docker-compose logs nginx - -log-web: - docker-compose logs web - -log-ps: - docker-compose logs postgres - -log-rmq: - docker-compose logs rabbitmq - -log-worker: - docker-compose logs worker diff --git a/tools/pharos-dashboard/__init__.py b/tools/pharos-dashboard/__init__.py deleted file mode 100644 index ce1acf36..00000000 --- a/tools/pharos-dashboard/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -##############################################################################
\ No newline at end of file diff --git a/tools/pharos-dashboard/booking_communication_agent.py b/tools/pharos-dashboard/booking_communication_agent.py deleted file mode 100644 index c52e98bd..00000000 --- a/tools/pharos-dashboard/booking_communication_agent.py +++ /dev/null @@ -1,42 +0,0 @@ -from dashboard_notification.notification import Notification -from dashboard_api.api import DashboardAPI - -CONFIG = { - 'dashboard_ip': '127.0.0.1', - 'dashboard_url': 'http://127.0.0.1', - 'api_token': 'f33ff43c85ecb13f5d0632c05dbb0a7d85a5a8d1', - 'user': 'opnfv', - 'password': 'opnfvopnfv' -} - -api = DashboardAPI(CONFIG['dashboard_url'], api_token=CONFIG['api_token'], verbose=True) - - -def booking_start(message): - content = message.content - booking = api.get_booking(id=content['booking_id']) - - # do something here... - - # notify dashboard - api.post_resource_status(resource_id=booking['resource_id'], type='info', title='pod setup', - content='details') - - -def booking_end(message): - # do something here... - - # notify dashboard - api.post_resource_status(resource_id=message.content['resource_id'], type='info', - title='booking end', content='details') - - -def main(): - with Notification(CONFIG['dashboard_ip'], CONFIG['user'], CONFIG['password']) as notification: - notification.register(booking_start, 'Arm POD 2', 'booking_start') - notification.register(booking_end, 'Arm POD 2', 'booking_end') - notification.receive() # wait for notifications - - -if __name__ == "__main__": - main() diff --git a/tools/pharos-dashboard/config.env.sample b/tools/pharos-dashboard/config.env.sample deleted file mode 100644 index 060841c2..00000000 --- a/tools/pharos-dashboard/config.env.sample +++ /dev/null @@ -1,24 +0,0 @@ -DASHBOARD_URL=http://labs.opnfv.org - -# SECURITY WARNING: don't run with debug turned on in production! -DEBUG=False - -DB_NAME=sample_name -DB_USER=sample_user -DB_PASS=sample_pass -DB_SERVICE=postgres -DB_PORT=5432 - -# SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY=http://www.miniwebtool.com/django-secret-key-generator/ - -OAUTH_CONSUMER_KEY=sample_key -OAUTH_CONSUMER_SECRET=sample_secret - -JIRA_URL=sample_url -JIRA_USER_NAME=sample_jira_user -JIRA_USER_PASSWORD=sample_jira_pass - -# Rabbitmq -RABBITMQ_USER=opnfv -RABBITMQ_PASSWORD=opnfvopnfv diff --git a/tools/pharos-dashboard/config/nginx/pharos_dashboard.conf b/tools/pharos-dashboard/config/nginx/pharos_dashboard.conf deleted file mode 100644 index 87b6f8e8..00000000 --- a/tools/pharos-dashboard/config/nginx/pharos_dashboard.conf +++ /dev/null @@ -1,24 +0,0 @@ -upstream web { - ip_hash; - server web:8000; -} - -# portal -server { - listen 80; - server_name localhost; - charset utf-8; - - location /static { - alias /static; - } - - location /media { - alias /media; - } - - location / { - proxy_set_header Host $host; - proxy_pass http://web/; - } -} diff --git a/tools/pharos-dashboard/config/postgres/docker-entrypoint-initdb.d/pharos_dashboard.sh b/tools/pharos-dashboard/config/postgres/docker-entrypoint-initdb.d/pharos_dashboard.sh deleted file mode 100755 index 526228a8..00000000 --- a/tools/pharos-dashboard/config/postgres/docker-entrypoint-initdb.d/pharos_dashboard.sh +++ /dev/null @@ -1,14 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -#!/bin/env bash - -psql -U postgres -c "CREATE USER $DB_USER PASSWORD '$DB_PASS'" -psql -U postgres -c "CREATE DATABASE $DB_NAME OWNER $DB_USER" diff --git a/tools/pharos-dashboard/dashboard_api/__init__.py b/tools/pharos-dashboard/dashboard_api/__init__.py deleted file mode 100644 index ce1acf36..00000000 --- a/tools/pharos-dashboard/dashboard_api/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -##############################################################################
\ No newline at end of file diff --git a/tools/pharos-dashboard/dashboard_api/api.py b/tools/pharos-dashboard/dashboard_api/api.py deleted file mode 100644 index d40e0aa4..00000000 --- a/tools/pharos-dashboard/dashboard_api/api.py +++ /dev/null @@ -1,91 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -import logging - -import requests - -URLS = { - 'resources': '/api/resources/', - 'servers': '/api/servers/', - 'bookings': '/api/bookings', - 'resource_status': '/api/resource_status/', -} - -class DashboardAPI(object): - def __init__(self, dashboard_url, api_token='', verbose=False): - self._api_token = api_token - self._verbose = verbose - self._resources_url = dashboard_url + URLS['resources'] - self._servers_url = dashboard_url + URLS['servers'] - self._bookings_url = dashboard_url + URLS['bookings'] - self._resources_status_url = dashboard_url + URLS['resource_status'] - self._logger = logging.getLogger(__name__) - - def get_all_resources(self): - return self._get_json(self._resources_url) - - def get_resource(self, id='', name='', url=''): - if url != '': - return self._get_json(url)[0] - url = self._resources_url + self._url_parameter(id=id, name=name) - return self._get_json(url)[0] - - def get_all_bookings(self): - return self._get_json(self._bookings_url) - - def get_resource_bookings(self, resource_id): - url = self._bookings_url + self._url_parameter(resource_id=resource_id) - return self._get_json(url) - - def get_booking(self, id): - url = self._bookings_url + self._url_parameter(id=id) - return self._get_json(url)[0] - - def post_resource_status(self, resource_id, type, title, content): - data = { - 'resource': resource_id, - 'type': type, - 'title': title, - 'content': content - } - return self._post_json(self._resources_status_url, data) - - def get_url(self, url): - return self._get_json(url) - - def _url_parameter(self, **kwargs): - res = '' - prefix = '?' - for key, val in kwargs.items(): - res += prefix + key + '=' + str(val) - prefix = '&' - return res - - def _get_json(self, url): - try: - response = requests.get(url) - if self._verbose: - print('Get JSON: ' + url) - print(response.status_code, response.content) - return response.json() - except requests.exceptions.RequestException as e: - self._logger.exception(e) - except ValueError as e: - self._logger.exception(e) - - def _post_json(self, url, json): - if self._api_token == '': - raise Exception('Need api token to POST data.') - response = requests.post(url, json, headers={'Authorization': 'Token ' + self._api_token}) - if self._verbose: - print('Post JSON: ' + url) - print(response.status_code, response.content) - return response.status_code diff --git a/tools/pharos-dashboard/dashboard_notification/__init__.py b/tools/pharos-dashboard/dashboard_notification/__init__.py deleted file mode 100644 index b5914ce7..00000000 --- a/tools/pharos-dashboard/dashboard_notification/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - diff --git a/tools/pharos-dashboard/dashboard_notification/notification.py b/tools/pharos-dashboard/dashboard_notification/notification.py deleted file mode 100644 index 6843c761..00000000 --- a/tools/pharos-dashboard/dashboard_notification/notification.py +++ /dev/null @@ -1,120 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - -import jsonpickle -import pika - - -class Message(object): - def __init__(self, type, topic, content): - self.type = type - self.topic = topic - self.content = content - - -class Notification(object): - """ - This class can be used by the dashboard and the labs to exchange notifications about booking - events and pod status. It utilizes rabbitmq to communicate. - - Notifications are associated to an event and to a topic. - Events are: - [ 'booking_start', 'booking_end'] - The topic is usually a POD name, ie: - 'Intel POD 2' - """ - - def __init__(self, dashboard_url, user=None, password=None, verbose=False): - self.rabbitmq_broker = dashboard_url - self.verbose = verbose - if user is None and password is None: - self._connection = pika.BlockingConnection(pika.ConnectionParameters( - host=self.rabbitmq_broker)) - else: - self.credentials = pika.PlainCredentials(user, password) - self._connection = pika.BlockingConnection(pika.ConnectionParameters( - credentials=self.credentials, - host=self.rabbitmq_broker)) - self._registry = {} - self._channel = self._connection.channel() - self._channel.exchange_declare(exchange='notifications', type='topic') - self._result = self._channel.queue_declare(exclusive=True, durable=True) - self._queue_name = self._result.method.queue - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_val, exc_tb): - self._connection.close() - - def register(self, function, topic, type='all'): - """ - Registers a function to be called for the specified event. - :param function: the function to register - :param event: the event type - :param regex: a regex to specify for wich topics the function will be called. Some - possible Expressions can be: - 'Intel POD 2' : Intel POD 2 - """ - - if topic not in self._registry: - self._registry[topic] = [(function, type)] - else: - self._registry[topic].append((function, type)) - - def receive(self): - """ - Start receiving notifications. This is a blocking operation, if a notification is received, - the registered functions will be called. - """ - if self.verbose: - print('Start receiving Notifications. Keys: ', self._registry.keys()) - self._receive_message(self._registry.keys()) - - def send(self, message): - """ - Send an event notification. - :param event: the event type - :param topic: the pod name - :param content: a JSON-serializable dictionary - """ - self._send_message(message) - - def _send_message(self, message): - routing_key = message.topic - message_json = jsonpickle.encode(message) - self._channel.basic_publish(exchange='notifications', - routing_key=routing_key, - body=message_json, - properties=pika.BasicProperties( - content_type='application/json', - delivery_mode=2, # make message persistent - )) - if self.verbose: - print(" [x] Sent %r:%r" % (routing_key, message_json)) - - def _receive_message(self, binding_keys): - for key in binding_keys: - self._channel.queue_bind(exchange='notifications', - queue=self._queue_name, - routing_key=key) - self._channel.basic_consume(self._message_callback, - queue=self._queue_name) - self._channel.start_consuming() - - def _message_callback(self, ch, method, properties, body): - if self.verbose: - print(" [x] Got %r:%r" % (method.routing_key, body)) - if method.routing_key not in self._registry: - return - for func, type in self._registry[method.routing_key]: - message = jsonpickle.decode(body.decode()) - if message.type == type: - func(message) - ch.basic_ack(delivery_tag=method.delivery_tag) diff --git a/tools/pharos-dashboard/docker-compose.yml b/tools/pharos-dashboard/docker-compose.yml deleted file mode 100644 index 44a263f0..00000000 --- a/tools/pharos-dashboard/docker-compose.yml +++ /dev/null @@ -1,77 +0,0 @@ ---- -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -version: '2' -services: - nginx: - restart: always - image: nginx:latest - container_name: ng01 - ports: - - "80:80" - volumes: - - ./config/nginx:/etc/nginx/conf.d - - /var/lib/pharos_dashboard/static:/static - - /var/lib/pharos_dashboard/media:/media - depends_on: - - web - - web: - restart: always - build: ./web/ - container_name: dg01 - # yamllint disable rule:line-length - command: bash -c "python manage.py migrate && python manage.py collectstatic --no-input && gunicorn pharos_dashboard.wsgi -b 0.0.0.0:8000" - # yamllint enable rule:line-length - depends_on: - - postgres - links: - - postgres - env_file: config.env - volumes: - - ./:/pharos_dashboard - - /var/lib/pharos_dashboard/static:/static - - /var/lib/pharos_dashboard/media:/media - expose: - - "8000" - - postgres: - restart: always - image: postgres:latest - container_name: ps01 - env_file: config.env - volumes: - - ./config/postgres/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d - - pharos-data:/var/lib/postgresql/data - - rabbitmq: - restart: always - build: ./rabbitmq/ - container_name: rm01 - env_file: config.env - ports: - - "5672:5672" - - worker: - restart: always - build: ./worker/ - # yamllint disable rule:line-length - command: bash -c "celery -A pharos_dashboard worker -l info -B --schedule=~/celerybeat-schedule" - # yamllint enable rule:line-length - env_file: config.env - links: - - postgres - - rabbitmq - volumes: - - ./:/pharos_dashboard -volumes: - pharos-data: - external: true diff --git a/tools/pharos-dashboard/rabbitmq/Dockerfile b/tools/pharos-dashboard/rabbitmq/Dockerfile deleted file mode 100644 index 71162a45..00000000 --- a/tools/pharos-dashboard/rabbitmq/Dockerfile +++ /dev/null @@ -1,4 +0,0 @@ -FROM rabbitmq - -ADD init.sh /init.sh -CMD ["/init.sh"]
\ No newline at end of file diff --git a/tools/pharos-dashboard/rabbitmq/init.sh b/tools/pharos-dashboard/rabbitmq/init.sh deleted file mode 100755 index 9d04dd11..00000000 --- a/tools/pharos-dashboard/rabbitmq/init.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -# Create Rabbitmq user -( sleep 10 ; \ -rabbitmqctl add_user $RABBITMQ_USER $RABBITMQ_PASSWORD 2>/dev/null ; \ -rabbitmqctl set_user_tags $RABBITMQ_USER administrator ; \ -rabbitmqctl set_permissions -p / $RABBITMQ_USER ".*" ".*" ".*" ; \ -echo "*** User '$RABBITMQ_USER' with password '$RABBITMQ_PASSWORD' completed. ***") & - -rabbitmq-server $@ diff --git a/tools/pharos-dashboard/readme.txt b/tools/pharos-dashboard/readme.txt deleted file mode 100644 index 2a259129..00000000 --- a/tools/pharos-dashboard/readme.txt +++ /dev/null @@ -1,36 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -The dashboard is deployed using docker-compose. -Application / database files are saved in /var/lib/pharos_dashboard/. - -Deployment: - -- clone the repository -- complete the config.env.sample file and save it as config.env -- install docker, docker-compose and bower -- run 'bower install' in ./src/static/ to fetch javascript dependencies -- run 'make build' to build the containers -- run 'make data' -- run 'make up' to run the dashboard - -Updating: - -- make stop -- git pull -- run 'bower install' if javascript dependencies changed -- make build -- make start - -If there is migrations that need user input (like renaming a field), they need to be run manually! - -Logs / Shell access: - -- there is some shortcuts in the makefile diff --git a/tools/pharos-dashboard/src/__init__.py b/tools/pharos-dashboard/src/__init__.py deleted file mode 100644 index ce1acf36..00000000 --- a/tools/pharos-dashboard/src/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -##############################################################################
\ No newline at end of file diff --git a/tools/pharos-dashboard/src/account/__init__.py b/tools/pharos-dashboard/src/account/__init__.py deleted file mode 100644 index b5914ce7..00000000 --- a/tools/pharos-dashboard/src/account/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - diff --git a/tools/pharos-dashboard/src/account/admin.py b/tools/pharos-dashboard/src/account/admin.py deleted file mode 100644 index 18b2e1a8..00000000 --- a/tools/pharos-dashboard/src/account/admin.py +++ /dev/null @@ -1,15 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -from django.contrib import admin - -from account.models import UserProfile - -admin.site.register(UserProfile)
\ No newline at end of file diff --git a/tools/pharos-dashboard/src/account/apps.py b/tools/pharos-dashboard/src/account/apps.py deleted file mode 100644 index 9814648f..00000000 --- a/tools/pharos-dashboard/src/account/apps.py +++ /dev/null @@ -1,15 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -from django.apps import AppConfig - - -class AccountsConfig(AppConfig): - name = 'account' diff --git a/tools/pharos-dashboard/src/account/forms.py b/tools/pharos-dashboard/src/account/forms.py deleted file mode 100644 index 7653e2b1..00000000 --- a/tools/pharos-dashboard/src/account/forms.py +++ /dev/null @@ -1,22 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -import django.forms as forms -import pytz as pytz - -from account.models import UserProfile - - -class AccountSettingsForm(forms.ModelForm): - class Meta: - model = UserProfile - fields = ['company', 'ssh_public_key', 'pgp_public_key', 'timezone'] - - timezone = forms.ChoiceField(choices=[(x, x) for x in pytz.common_timezones], initial='UTC') diff --git a/tools/pharos-dashboard/src/account/jira_util.py b/tools/pharos-dashboard/src/account/jira_util.py deleted file mode 100644 index fdb87f77..00000000 --- a/tools/pharos-dashboard/src/account/jira_util.py +++ /dev/null @@ -1,65 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -import base64 -import os - -import oauth2 as oauth -from django.conf import settings -from jira import JIRA -from tlslite.utils import keyfactory - - -class SignatureMethod_RSA_SHA1(oauth.SignatureMethod): - name = 'RSA-SHA1' - - def signing_base(self, request, consumer, token): - if not hasattr(request, 'normalized_url') or request.normalized_url is None: - raise ValueError("Base URL for request is not set.") - - sig = ( - oauth.escape(request.method), - oauth.escape(request.normalized_url), - oauth.escape(request.get_normalized_parameters()), - ) - - key = '%s&' % oauth.escape(consumer.secret) - if token: - key += oauth.escape(token.secret) - raw = '&'.join(sig) - return key, raw - - def sign(self, request, consumer, token): - """Builds the base signature string.""" - key, raw = self.signing_base(request, consumer, token) - - module_dir = os.path.dirname(__file__) # get current directory - with open(module_dir + '/rsa.pem', 'r') as f: - data = f.read() - privateKeyString = data.strip() - privatekey = keyfactory.parsePrivateKey(privateKeyString) - raw = str.encode(raw) - signature = privatekey.hashAndSign(raw) - return base64.b64encode(signature) - - -def get_jira(user): - module_dir = os.path.dirname(__file__) # get current directory - with open(module_dir + '/rsa.pem', 'r') as f: - key_cert = f.read() - - oauth_dict = { - 'access_token': user.userprofile.oauth_token, - 'access_token_secret': user.userprofile.oauth_secret, - 'consumer_key': settings.OAUTH_CONSUMER_KEY, - 'key_cert': key_cert - } - - return JIRA(server=settings.JIRA_URL, oauth=oauth_dict)
\ No newline at end of file diff --git a/tools/pharos-dashboard/src/account/middleware.py b/tools/pharos-dashboard/src/account/middleware.py deleted file mode 100644 index 0f1dbd86..00000000 --- a/tools/pharos-dashboard/src/account/middleware.py +++ /dev/null @@ -1,32 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -from django.utils import timezone -from django.utils.deprecation import MiddlewareMixin - -from account.models import UserProfile - - -class TimezoneMiddleware(MiddlewareMixin): - """ - Activate the timezone from request.user.userprofile if user is authenticated, - deactivate the timezone otherwise and use default (UTC) - """ - def process_request(self, request): - if request.user.is_authenticated: - try: - tz = request.user.userprofile.timezone - timezone.activate(tz) - except UserProfile.DoesNotExist: - UserProfile.objects.create(user=request.user) - tz = request.user.userprofile.timezone - timezone.activate(tz) - else: - timezone.deactivate() diff --git a/tools/pharos-dashboard/src/account/migrations/0001_initial.py b/tools/pharos-dashboard/src/account/migrations/0001_initial.py deleted file mode 100644 index 591f7024..00000000 --- a/tools/pharos-dashboard/src/account/migrations/0001_initial.py +++ /dev/null @@ -1,38 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10 on 2016-11-03 13:33 -from __future__ import unicode_literals - -import account.models -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ] - - operations = [ - migrations.CreateModel( - name='UserProfile', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('timezone', models.CharField(default='UTC', max_length=100)), - ('ssh_public_key', models.FileField(blank=True, null=True, upload_to=account.models.upload_to)), - ('pgp_public_key', models.FileField(blank=True, null=True, upload_to=account.models.upload_to)), - ('company', models.CharField(max_length=200)), - ('oauth_token', models.CharField(max_length=1024)), - ('oauth_secret', models.CharField(max_length=1024)), - ('jira_url', models.CharField(default='', max_length=100)), - ('full_name', models.CharField(default='', max_length=100)), - ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), - ], - options={ - 'db_table': 'user_profile', - }, - ), - ] diff --git a/tools/pharos-dashboard/src/account/migrations/__init__.py b/tools/pharos-dashboard/src/account/migrations/__init__.py deleted file mode 100644 index b5914ce7..00000000 --- a/tools/pharos-dashboard/src/account/migrations/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - diff --git a/tools/pharos-dashboard/src/account/models.py b/tools/pharos-dashboard/src/account/models.py deleted file mode 100644 index c2e99028..00000000 --- a/tools/pharos-dashboard/src/account/models.py +++ /dev/null @@ -1,35 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -from django.contrib.auth.models import User -from django.db import models - - -def upload_to(object, filename): - return object.user.username + '/' + filename - -class UserProfile(models.Model): - user = models.OneToOneField(User, on_delete=models.CASCADE) - timezone = models.CharField(max_length=100, blank=False, default='UTC') - ssh_public_key = models.FileField(upload_to=upload_to, null=True, blank=True) - pgp_public_key = models.FileField(upload_to=upload_to, null=True, blank=True) - company = models.CharField(max_length=200, blank=False) - - oauth_token = models.CharField(max_length=1024, blank=False) - oauth_secret = models.CharField(max_length=1024, blank=False) - - jira_url = models.CharField(max_length=100, default='') - full_name = models.CharField(max_length=100, default='') - - class Meta: - db_table = 'user_profile' - - def __str__(self): - return self.user.username diff --git a/tools/pharos-dashboard/src/account/rsa.pem b/tools/pharos-dashboard/src/account/rsa.pem deleted file mode 100644 index dbd4eedd..00000000 --- a/tools/pharos-dashboard/src/account/rsa.pem +++ /dev/null @@ -1,17 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALRiMLAh9iimur8V -A7qVvdqxevEuUkW4K+2KdMXmnQbG9Aa7k7eBjK1S+0LYmVjPKlJGNXHDGuy5Fw/d -7rjVJ0BLB+ubPK8iA/Tw3hLQgXMRRGRXXCn8ikfuQfjUS1uZSatdLB81mydBETlJ -hI6GH4twrbDJCR2Bwy/XWXgqgGRzAgMBAAECgYBYWVtleUzavkbrPjy0T5FMou8H -X9u2AC2ry8vD/l7cqedtwMPp9k7TubgNFo+NGvKsl2ynyprOZR1xjQ7WgrgVB+mm -uScOM/5HVceFuGRDhYTCObE+y1kxRloNYXnx3ei1zbeYLPCHdhxRYW7T0qcynNmw -rn05/KO2RLjgQNalsQJBANeA3Q4Nugqy4QBUCEC09SqylT2K9FrrItqL2QKc9v0Z -zO2uwllCbg0dwpVuYPYXYvikNHHg+aCWF+VXsb9rpPsCQQDWR9TT4ORdzoj+Nccn -qkMsDmzt0EfNaAOwHOmVJ2RVBspPcxt5iN4HI7HNeG6U5YsFBb+/GZbgfBT3kpNG -WPTpAkBI+gFhjfJvRw38n3g/+UeAkwMI2TJQS4n8+hid0uus3/zOjDySH3XHCUno -cn1xOJAyZODBo47E+67R4jV1/gzbAkEAklJaspRPXP877NssM5nAZMU0/O/NGCZ+ -3jPgDUno6WbJn5cqm8MqWhW1xGkImgRk+fkDBquiq4gPiT898jusgQJAd5Zrr6Q8 -AO/0isr/3aa6O6NLQxISLKcPDk2NOccAfS/xOtfOz4sJYM3+Bs4Io9+dZGSDCA54 -Lw03eHTNQghS0A== ------END PRIVATE KEY----- - diff --git a/tools/pharos-dashboard/src/account/rsa.pub b/tools/pharos-dashboard/src/account/rsa.pub deleted file mode 100644 index cc50e45e..00000000 --- a/tools/pharos-dashboard/src/account/rsa.pub +++ /dev/null @@ -1,6 +0,0 @@ ------BEGIN PUBLIC KEY----- -MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC0YjCwIfYoprq/FQO6lb3asXrx -LlJFuCvtinTF5p0GxvQGu5O3gYytUvtC2JlYzypSRjVxwxrsuRcP3e641SdASwfr -mzyvIgP08N4S0IFzEURkV1wp/IpH7kH41EtbmUmrXSwfNZsnQRE5SYSOhh+LcK2w -yQkdgcMv11l4KoBkcwIDAQAB ------END PUBLIC KEY----- diff --git a/tools/pharos-dashboard/src/account/tasks.py b/tools/pharos-dashboard/src/account/tasks.py deleted file mode 100644 index bfb865dd..00000000 --- a/tools/pharos-dashboard/src/account/tasks.py +++ /dev/null @@ -1,34 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -from celery import shared_task -from django.contrib.auth.models import User -from jira import JIRAError - -from account.jira_util import get_jira - - -@shared_task -def sync_jira_accounts(): - users = User.objects.all() - for user in users: - jira = get_jira(user) - try: - user_dict = jira.myself() - except JIRAError: - # User can be anonymous (local django admin account) - continue - user.email = user_dict['emailAddress'] - user.userprofile.url = user_dict['self'] - user.userprofile.full_name = user_dict['displayName'] - print(user_dict) - - user.userprofile.save() - user.save()
\ No newline at end of file diff --git a/tools/pharos-dashboard/src/account/tests/__init__.py b/tools/pharos-dashboard/src/account/tests/__init__.py deleted file mode 100644 index b5914ce7..00000000 --- a/tools/pharos-dashboard/src/account/tests/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - diff --git a/tools/pharos-dashboard/src/account/tests/test_general.py b/tools/pharos-dashboard/src/account/tests/test_general.py deleted file mode 100644 index e8f483b5..00000000 --- a/tools/pharos-dashboard/src/account/tests/test_general.py +++ /dev/null @@ -1,60 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -from django.contrib.auth.models import User -from django.test import Client -from django.test import TestCase -from django.urls import reverse -from django.utils import timezone - -from account.models import UserProfile - - -class AccountMiddlewareTestCase(TestCase): - def setUp(self): - self.client = Client() - self.user1 = User.objects.create(username='user1') - self.user1.set_password('user1') - self.user1profile = UserProfile.objects.create(user=self.user1) - self.user1.save() - - def test_timezone_middleware(self): - """ - The timezone should be UTC for anonymous users, for authenticated users it should be set - to user.userprofile.timezone - """ - #default - self.assertEqual(timezone.get_current_timezone_name(), 'UTC') - - url = reverse('account:settings') - # anonymous request - self.client.get(url) - self.assertEqual(timezone.get_current_timezone_name(), 'UTC') - - # authenticated user with UTC timezone (userprofile default) - self.client.login(username='user1', password='user1') - self.client.get(url) - self.assertEqual(timezone.get_current_timezone_name(), 'UTC') - - # authenticated user with custom timezone (userprofile default) - self.user1profile.timezone = 'Etc/Greenwich' - self.user1profile.save() - self.client.get(url) - self.assertEqual(timezone.get_current_timezone_name(), 'Etc/Greenwich') - - # if there is no profile for a user, it should be created - user2 = User.objects.create(username='user2') - user2.set_password('user2') - user2.save() - self.client.login(username='user2', password='user2') - self.client.get(url) - self.assertTrue(user2.userprofile) - - diff --git a/tools/pharos-dashboard/src/account/urls.py b/tools/pharos-dashboard/src/account/urls.py deleted file mode 100644 index 3962a0c6..00000000 --- a/tools/pharos-dashboard/src/account/urls.py +++ /dev/null @@ -1,36 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -"""pharos_dashboard URL Configuration - -The `urlpatterns` list routes URLs to views. For more information please see: - https://docs.djangoproject.com/en/1.10/topics/http/urls/ -Examples: -Function views - 1. Add an import: from my_app import views - 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') -Class-based views - 1. Add an import: from other_app.views import Home - 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') -Including another URLconf - 1. Import the include() function: from django.conf.urls import url, include - 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) -""" -from django.conf.urls import url - -from account.views import * - -urlpatterns = [ - url(r'^settings/', AccountSettingsView.as_view(), name='settings'), - url(r'^authenticated/$', JiraAuthenticatedView.as_view(), name='authenticated'), - url(r'^login/$', JiraLoginView.as_view(), name='login'), - url(r'^logout/$', JiraLogoutView.as_view(), name='logout'), - url(r'^users/$', UserListView.as_view(), name='users'), -] diff --git a/tools/pharos-dashboard/src/account/views.py b/tools/pharos-dashboard/src/account/views.py deleted file mode 100644 index 17fbdc3a..00000000 --- a/tools/pharos-dashboard/src/account/views.py +++ /dev/null @@ -1,153 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -import os -import urllib - -import oauth2 as oauth -from django.conf import settings -from django.contrib import messages -from django.contrib.auth import logout, authenticate, login -from django.contrib.auth.decorators import login_required -from django.contrib.auth.mixins import LoginRequiredMixin -from django.contrib.auth.models import User -from django.urls import reverse -from django.utils.decorators import method_decorator -from django.views.generic import RedirectView, TemplateView, UpdateView -from jira import JIRA -from rest_framework.authtoken.models import Token - -from account.forms import AccountSettingsForm -from account.jira_util import SignatureMethod_RSA_SHA1 -from account.models import UserProfile - - -@method_decorator(login_required, name='dispatch') -class AccountSettingsView(UpdateView): - model = UserProfile - form_class = AccountSettingsForm - template_name_suffix = '_update_form' - - def get_success_url(self): - messages.add_message(self.request, messages.INFO, - 'Settings saved') - return '/' - - def get_object(self, queryset=None): - return self.request.user.userprofile - - def get_context_data(self, **kwargs): - token, created = Token.objects.get_or_create(user=self.request.user) - context = super(AccountSettingsView, self).get_context_data(**kwargs) - context.update({'title': "Settings", 'token': token}) - return context - - -class JiraLoginView(RedirectView): - def get_redirect_url(self, *args, **kwargs): - consumer = oauth.Consumer(settings.OAUTH_CONSUMER_KEY, settings.OAUTH_CONSUMER_SECRET) - client = oauth.Client(consumer) - client.set_signature_method(SignatureMethod_RSA_SHA1()) - - # Step 1. Get a request token from Jira. - try: - resp, content = client.request(settings.OAUTH_REQUEST_TOKEN_URL, "POST") - except Exception as e: - messages.add_message(self.request, messages.ERROR, - 'Error: Connection to Jira failed. Please contact an Administrator') - return '/' - if resp['status'] != '200': - messages.add_message(self.request, messages.ERROR, - 'Error: Connection to Jira failed. Please contact an Administrator') - return '/' - - # Step 2. Store the request token in a session for later use. - self.request.session['request_token'] = dict(urllib.parse.parse_qsl(content.decode())) - # Step 3. Redirect the user to the authentication URL. - url = settings.OAUTH_AUTHORIZE_URL + '?oauth_token=' + \ - self.request.session['request_token']['oauth_token'] + \ - '&oauth_callback=' + settings.OAUTH_CALLBACK_URL - return url - - -class JiraLogoutView(LoginRequiredMixin, RedirectView): - def get_redirect_url(self, *args, **kwargs): - logout(self.request) - return '/' - - -class JiraAuthenticatedView(RedirectView): - def get_redirect_url(self, *args, **kwargs): - # Step 1. Use the request token in the session to build a new client. - consumer = oauth.Consumer(settings.OAUTH_CONSUMER_KEY, settings.OAUTH_CONSUMER_SECRET) - token = oauth.Token(self.request.session['request_token']['oauth_token'], - self.request.session['request_token']['oauth_token_secret']) - client = oauth.Client(consumer, token) - client.set_signature_method(SignatureMethod_RSA_SHA1()) - - # Step 2. Request the authorized access token from Jira. - try: - resp, content = client.request(settings.OAUTH_ACCESS_TOKEN_URL, "POST") - except Exception as e: - messages.add_message(self.request, messages.ERROR, - 'Error: Connection to Jira failed. Please contact an Administrator') - return '/' - if resp['status'] != '200': - messages.add_message(self.request, messages.ERROR, - 'Error: Connection to Jira failed. Please contact an Administrator') - return '/' - - access_token = dict(urllib.parse.parse_qsl(content.decode())) - - module_dir = os.path.dirname(__file__) # get current directory - with open(module_dir + '/rsa.pem', 'r') as f: - key_cert = f.read() - - oauth_dict = { - 'access_token': access_token['oauth_token'], - 'access_token_secret': access_token['oauth_token_secret'], - 'consumer_key': settings.OAUTH_CONSUMER_KEY, - 'key_cert': key_cert - } - - jira = JIRA(server=settings.JIRA_URL, oauth=oauth_dict) - username = jira.current_user() - url = '/' - # Step 3. Lookup the user or create them if they don't exist. - try: - user = User.objects.get(username=username) - except User.DoesNotExist: - # Save our permanent token and secret for later. - user = User.objects.create_user(username=username, - password=access_token['oauth_token_secret']) - profile = UserProfile() - profile.user = user - profile.save() - url = reverse('account:settings') - user.userprofile.oauth_token = access_token['oauth_token'] - user.userprofile.oauth_secret = access_token['oauth_token_secret'] - user.userprofile.save() - user.set_password(access_token['oauth_token_secret']) - user.save() - user = authenticate(username=username, password=access_token['oauth_token_secret']) - login(self.request, user) - # redirect user to settings page to complete profile - return url - - -@method_decorator(login_required, name='dispatch') -class UserListView(TemplateView): - template_name = "account/user_list.html" - - def get_context_data(self, **kwargs): - users = User.objects.all() - context = super(UserListView, self).get_context_data(**kwargs) - context.update({'title': "Dashboard Users", 'users': users}) - return context diff --git a/tools/pharos-dashboard/src/api/__init__.py b/tools/pharos-dashboard/src/api/__init__.py deleted file mode 100644 index b5914ce7..00000000 --- a/tools/pharos-dashboard/src/api/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - diff --git a/tools/pharos-dashboard/src/api/migrations/__init__.py b/tools/pharos-dashboard/src/api/migrations/__init__.py deleted file mode 100644 index b5914ce7..00000000 --- a/tools/pharos-dashboard/src/api/migrations/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - diff --git a/tools/pharos-dashboard/src/api/serializers.py b/tools/pharos-dashboard/src/api/serializers.py deleted file mode 100644 index 237ca029..00000000 --- a/tools/pharos-dashboard/src/api/serializers.py +++ /dev/null @@ -1,39 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -from rest_framework import serializers - -from booking.models import Booking -from dashboard.models import Server, Resource, ResourceStatus - -class BookingSerializer(serializers.ModelSerializer): - installer_name = serializers.CharField(source='installer.name') - scenario_name = serializers.CharField(source='scenario.name') - - class Meta: - model = Booking - fields = ('id', 'resource_id', 'start', 'end', 'installer_name', 'scenario_name', 'purpose') - - -class ServerSerializer(serializers.ModelSerializer): - class Meta: - model = Server - fields = ('id', 'resource_id', 'name', 'model', 'cpu', 'ram', 'storage') - - -class ResourceSerializer(serializers.ModelSerializer): - class Meta: - model = Resource - fields = ('id', 'name', 'description', 'url', 'server_set') - -class ResourceStatusSerializer(serializers.ModelSerializer): - class Meta: - model = ResourceStatus - fields = ('id', 'resource', 'timestamp','type', 'title', 'content') diff --git a/tools/pharos-dashboard/src/api/urls.py b/tools/pharos-dashboard/src/api/urls.py deleted file mode 100644 index a4a4b2ff..00000000 --- a/tools/pharos-dashboard/src/api/urls.py +++ /dev/null @@ -1,40 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -"""pharos_dashboard URL Configuration - -The `urlpatterns` list routes URLs to views. For more information please see: - https://docs.djangoproject.com/en/1.10/topics/http/urls/ -Examples: -Function views - 1. Add an import: from my_app import views - 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') -Class-based views - 1. Add an import: from other_app.views import Home - 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') -Including another URLconf - 1. Import the include() function: from django.conf.urls import url, include - 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) -""" -from django.conf.urls import url, include -from rest_framework import routers - -from api.views import * - -router = routers.DefaultRouter() -router.register(r'resources', ResourceViewSet) -router.register(r'servers', ServerViewSet) -router.register(r'bookings', BookingViewSet) -router.register(r'resource_status', ResourceStatusViewSet) - -urlpatterns = [ - url(r'^', include(router.urls)), - url(r'^token$', GenerateTokenView.as_view(), name='generate_token'), -]
\ No newline at end of file diff --git a/tools/pharos-dashboard/src/api/views.py b/tools/pharos-dashboard/src/api/views.py deleted file mode 100644 index 84fa1b52..00000000 --- a/tools/pharos-dashboard/src/api/views.py +++ /dev/null @@ -1,53 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -from django.contrib.auth.decorators import login_required -from django.shortcuts import redirect -from django.utils.decorators import method_decorator -from django.views import View -from rest_framework import viewsets -from rest_framework.authtoken.models import Token - -from api.serializers import * -from booking.models import Booking -from dashboard.models import Resource, Server, ResourceStatus - - -class BookingViewSet(viewsets.ModelViewSet): - queryset = Booking.objects.all() - serializer_class = BookingSerializer - filter_fields = ('resource', 'id') - - -class ServerViewSet(viewsets.ModelViewSet): - queryset = Server.objects.all() - serializer_class = ServerSerializer - filter_fields = ('resource', 'name') - - -class ResourceViewSet(viewsets.ModelViewSet): - queryset = Resource.objects.all() - serializer_class = ResourceSerializer - filter_fields = ('name', 'id') - -class ResourceStatusViewSet(viewsets.ModelViewSet): - queryset = ResourceStatus.objects.all() - serializer_class = ResourceStatusSerializer - - -@method_decorator(login_required, name='dispatch') -class GenerateTokenView(View): - def get(self, request, *args, **kwargs): - user = self.request.user - token, created = Token.objects.get_or_create(user=user) - if not created: - token.delete() - Token.objects.create(user=user) - return redirect('account:settings') diff --git a/tools/pharos-dashboard/src/booking/__init__.py b/tools/pharos-dashboard/src/booking/__init__.py deleted file mode 100644 index b5914ce7..00000000 --- a/tools/pharos-dashboard/src/booking/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - diff --git a/tools/pharos-dashboard/src/booking/admin.py b/tools/pharos-dashboard/src/booking/admin.py deleted file mode 100644 index d883be1c..00000000 --- a/tools/pharos-dashboard/src/booking/admin.py +++ /dev/null @@ -1,17 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -from django.contrib import admin - -from booking.models import * - -admin.site.register(Booking) -admin.site.register(Installer) -admin.site.register(Scenario)
\ No newline at end of file diff --git a/tools/pharos-dashboard/src/booking/apps.py b/tools/pharos-dashboard/src/booking/apps.py deleted file mode 100644 index 99bf115f..00000000 --- a/tools/pharos-dashboard/src/booking/apps.py +++ /dev/null @@ -1,15 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -from django.apps import AppConfig - - -class BookingConfig(AppConfig): - name = 'booking' diff --git a/tools/pharos-dashboard/src/booking/forms.py b/tools/pharos-dashboard/src/booking/forms.py deleted file mode 100644 index 2dbfacb0..00000000 --- a/tools/pharos-dashboard/src/booking/forms.py +++ /dev/null @@ -1,23 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -import django.forms as forms - -from booking.models import Installer, Scenario - - -class BookingForm(forms.Form): - fields = ['start', 'end', 'purpose', 'installer', 'scenario'] - - start = forms.DateTimeField() - end = forms.DateTimeField() - purpose = forms.CharField(max_length=300) - installer = forms.ModelChoiceField(queryset=Installer.objects.all(), required=False) - scenario = forms.ModelChoiceField(queryset=Scenario.objects.all(), required=False)
\ No newline at end of file diff --git a/tools/pharos-dashboard/src/booking/migrations/0001_initial.py b/tools/pharos-dashboard/src/booking/migrations/0001_initial.py deleted file mode 100644 index 6932daea..00000000 --- a/tools/pharos-dashboard/src/booking/migrations/0001_initial.py +++ /dev/null @@ -1,68 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10 on 2016-11-03 13:33 -from __future__ import unicode_literals - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - ('dashboard', '0001_initial'), - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ] - - operations = [ - migrations.CreateModel( - name='Booking', - fields=[ - ('id', models.AutoField(primary_key=True, serialize=False)), - ('start', models.DateTimeField()), - ('end', models.DateTimeField()), - ('jira_issue_id', models.IntegerField(null=True)), - ('jira_issue_status', models.CharField(max_length=50)), - ('purpose', models.CharField(max_length=300)), - ], - options={ - 'db_table': 'booking', - }, - ), - migrations.CreateModel( - name='Installer', - fields=[ - ('id', models.AutoField(primary_key=True, serialize=False)), - ('name', models.CharField(max_length=30)), - ], - ), - migrations.CreateModel( - name='Scenario', - fields=[ - ('id', models.AutoField(primary_key=True, serialize=False)), - ('name', models.CharField(max_length=300)), - ], - ), - migrations.AddField( - model_name='booking', - name='installer', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='booking.Installer'), - ), - migrations.AddField( - model_name='booking', - name='resource', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='dashboard.Resource'), - ), - migrations.AddField( - model_name='booking', - name='scenario', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='booking.Scenario'), - ), - migrations.AddField( - model_name='booking', - name='user', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), - ), - ] diff --git a/tools/pharos-dashboard/src/booking/migrations/__init__.py b/tools/pharos-dashboard/src/booking/migrations/__init__.py deleted file mode 100644 index b5914ce7..00000000 --- a/tools/pharos-dashboard/src/booking/migrations/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - diff --git a/tools/pharos-dashboard/src/booking/models.py b/tools/pharos-dashboard/src/booking/models.py deleted file mode 100644 index 0b3fa3b1..00000000 --- a/tools/pharos-dashboard/src/booking/models.py +++ /dev/null @@ -1,77 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -from django.conf import settings -from django.contrib.auth.models import User -from django.db import models -from jira import JIRA -from jira import JIRAError - -from dashboard.models import Resource - - -class Installer(models.Model): - id = models.AutoField(primary_key=True) - name = models.CharField(max_length=30) - - def __str__(self): - return self.name - -class Scenario(models.Model): - id = models.AutoField(primary_key=True) - name = models.CharField(max_length=300) - - def __str__(self): - return self.name - - -class Booking(models.Model): - id = models.AutoField(primary_key=True) - user = models.ForeignKey(User, models.CASCADE) # delete if user is deleted - resource = models.ForeignKey(Resource, models.PROTECT) - start = models.DateTimeField() - end = models.DateTimeField() - jira_issue_id = models.IntegerField(null=True) - jira_issue_status = models.CharField(max_length=50) - - installer = models.ForeignKey(Installer, models.DO_NOTHING, null=True) - scenario = models.ForeignKey(Scenario, models.DO_NOTHING, null=True) - purpose = models.CharField(max_length=300, blank=False) - - class Meta: - db_table = 'booking' - - def get_jira_issue(self): - try: - jira = JIRA(server=settings.JIRA_URL, - basic_auth=(settings.JIRA_USER_NAME, settings.JIRA_USER_PASSWORD)) - issue = jira.issue(self.jira_issue_id) - return issue - except JIRAError: - return None - - def save(self, *args, **kwargs): - """ - Save the booking if self.user is authorized and there is no overlapping booking. - Raise PermissionError if the user is not authorized - Raise ValueError if there is an overlapping booking - """ - if self.start >= self.end: - raise ValueError('Start date is after end date') - # conflicts end after booking starts, and start before booking ends - conflicting_dates = Booking.objects.filter(resource=self.resource).exclude(id=self.id) - conflicting_dates = conflicting_dates.filter(end__gt=self.start) - conflicting_dates = conflicting_dates.filter(start__lt=self.end) - if conflicting_dates.count() > 0: - raise ValueError('This booking overlaps with another booking') - return super(Booking, self).save(*args, **kwargs) - - def __str__(self): - return str(self.resource) + ' from ' + str(self.start) + ' until ' + str(self.end) diff --git a/tools/pharos-dashboard/src/booking/tests/__init__.py b/tools/pharos-dashboard/src/booking/tests/__init__.py deleted file mode 100644 index b5914ce7..00000000 --- a/tools/pharos-dashboard/src/booking/tests/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - diff --git a/tools/pharos-dashboard/src/booking/tests/test_models.py b/tools/pharos-dashboard/src/booking/tests/test_models.py deleted file mode 100644 index b4cd1133..00000000 --- a/tools/pharos-dashboard/src/booking/tests/test_models.py +++ /dev/null @@ -1,94 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -from datetime import timedelta - -from django.contrib.auth.models import Permission -from django.test import TestCase -from django.utils import timezone - -from booking.models import * -from dashboard.models import Resource -from jenkins.models import JenkinsSlave - - -class BookingModelTestCase(TestCase): - def setUp(self): - self.slave = JenkinsSlave.objects.create(name='test', url='test') - self.owner = User.objects.create(username='owner') - - self.res1 = Resource.objects.create(name='res1', slave=self.slave, description='x', - url='x',owner=self.owner) - self.res2 = Resource.objects.create(name='res2', slave=self.slave, description='x', - url='x',owner=self.owner) - - self.user1 = User.objects.create(username='user1') - - self.add_booking_perm = Permission.objects.get(codename='add_booking') - self.user1.user_permissions.add(self.add_booking_perm) - - self.user1 = User.objects.get(pk=self.user1.id) - - self.installer = Installer.objects.create(name='TestInstaller') - self.scenario = Scenario.objects.create(name='TestScenario') - - def test_start_end(self): - """ - if the start of a booking is greater or equal then the end, saving should raise a - ValueException - """ - start = timezone.now() - end = start - timedelta(weeks=1) - self.assertRaises(ValueError, Booking.objects.create, start=start, end=end, - resource=self.res1, user=self.user1) - end = start - self.assertRaises(ValueError, Booking.objects.create, start=start, end=end, - resource=self.res1, user=self.user1) - - def test_conflicts(self): - """ - saving an overlapping booking on the same resource should raise a ValueException - saving for different resources should succeed - """ - start = timezone.now() - end = start + timedelta(weeks=1) - self.assertTrue( - Booking.objects.create(start=start, end=end, user=self.user1, resource=self.res1)) - - self.assertRaises(ValueError, Booking.objects.create, start=start, - end=end, resource=self.res1, user=self.user1) - self.assertRaises(ValueError, Booking.objects.create, start=start + timedelta(days=1), - end=end - timedelta(days=1), resource=self.res1, user=self.user1) - - self.assertRaises(ValueError, Booking.objects.create, start=start - timedelta(days=1), - end=end, resource=self.res1, user=self.user1) - self.assertRaises(ValueError, Booking.objects.create, start=start - timedelta(days=1), - end=end - timedelta(days=1), resource=self.res1, user=self.user1) - - self.assertRaises(ValueError, Booking.objects.create, start=start, - end=end + timedelta(days=1), resource=self.res1, user=self.user1) - self.assertRaises(ValueError, Booking.objects.create, start=start + timedelta(days=1), - end=end + timedelta(days=1), resource=self.res1, user=self.user1) - - self.assertTrue(Booking.objects.create(start=start - timedelta(days=1), end=start, - user=self.user1, resource=self.res1)) - self.assertTrue(Booking.objects.create(start=end, end=end + timedelta(days=1), - user=self.user1, resource=self.res1)) - - self.assertTrue( - Booking.objects.create(start=start - timedelta(days=2), end=start - timedelta(days=1), - user=self.user1, resource=self.res1)) - self.assertTrue( - Booking.objects.create(start=end + timedelta(days=1), end=end + timedelta(days=2), - user=self.user1, resource=self.res1)) - self.assertTrue( - Booking.objects.create(start=start, end=end, - user=self.user1, resource=self.res2, scenario=self.scenario, - installer=self.installer))
\ No newline at end of file diff --git a/tools/pharos-dashboard/src/booking/tests/test_views.py b/tools/pharos-dashboard/src/booking/tests/test_views.py deleted file mode 100644 index c1da013c..00000000 --- a/tools/pharos-dashboard/src/booking/tests/test_views.py +++ /dev/null @@ -1,106 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -from datetime import timedelta - -from django.test import Client -from django.test import TestCase -from django.urls import reverse -from django.utils import timezone -from django.utils.encoding import force_text -from registration.forms import User - -from account.models import UserProfile -from booking.models import Booking -from dashboard.models import Resource -from jenkins.models import JenkinsSlave - - -class BookingViewTestCase(TestCase): - def setUp(self): - self.client = Client() - self.slave = JenkinsSlave.objects.create(name='test', url='test') - self.owner = User.objects.create(username='owner') - self.res1 = Resource.objects.create(name='res1', slave=self.slave, description='x', - url='x',owner=self.owner) - self.user1 = User.objects.create(username='user1') - self.user1.set_password('user1') - self.user1profile = UserProfile.objects.create(user=self.user1) - self.user1.save() - - self.user1 = User.objects.get(pk=self.user1.id) - - - def test_resource_bookings_json(self): - url = reverse('booking:bookings_json', kwargs={'resource_id': 0}) - self.assertEqual(self.client.get(url).status_code, 404) - - url = reverse('booking:bookings_json', kwargs={'resource_id': self.res1.id}) - response = self.client.get(url) - self.assertEqual(response.status_code, 200) - self.assertJSONEqual(force_text(response.content), {"bookings": []}) - booking1 = Booking.objects.create(start=timezone.now(), - end=timezone.now() + timedelta(weeks=1), user=self.user1, - resource=self.res1) - response = self.client.get(url) - json = response.json() - self.assertEqual(response.status_code, 200) - self.assertIn('bookings', json) - self.assertEqual(len(json['bookings']), 1) - self.assertIn('start', json['bookings'][0]) - self.assertIn('end', json['bookings'][0]) - self.assertIn('id', json['bookings'][0]) - self.assertIn('purpose', json['bookings'][0]) - - def test_booking_form_view(self): - url = reverse('booking:create', kwargs={'resource_id': 0}) - self.assertEqual(self.client.get(url).status_code, 404) - - # authenticated user - url = reverse('booking:create', kwargs={'resource_id': self.res1.id}) - self.client.login(username='user1',password='user1') - response = self.client.get(url) - self.assertEqual(response.status_code, 200) - self.assertTemplateUsed('booking/booking_calendar.html') - self.assertTemplateUsed('booking/booking_form.html') - self.assertIn('resource', response.context) - - - def test_booking_view(self): - start = timezone.now() - end = start + timedelta(weeks=1) - booking = Booking.objects.create(start=start, end=end, user=self.user1, resource=self.res1) - - url = reverse('booking:detail', kwargs={'booking_id':0}) - response = self.client.get(url) - self.assertEqual(response.status_code, 404) - - url = reverse('booking:detail', kwargs={'booking_id':booking.id}) - response = self.client.get(url) - self.assertEqual(response.status_code, 200) - self.assertTemplateUsed('booking/booking_detail.html') - self.assertIn('booking', response.context) - - def test_booking_list_view(self): - start = timezone.now() - timedelta(weeks=2) - end = start + timedelta(weeks=1) - Booking.objects.create(start=start, end=end, user=self.user1, resource=self.res1) - - url = reverse('booking:list') - response = self.client.get(url) - self.assertEqual(response.status_code, 200) - self.assertTemplateUsed('booking/booking_list.html') - self.assertTrue(len(response.context['bookings']) == 0) - - start = timezone.now() - end = start + timedelta(weeks=1) - Booking.objects.create(start=start, end=end, user=self.user1, resource=self.res1) - response = self.client.get(url) - self.assertTrue(len(response.context['bookings']) == 1)
\ No newline at end of file diff --git a/tools/pharos-dashboard/src/booking/urls.py b/tools/pharos-dashboard/src/booking/urls.py deleted file mode 100644 index 9e013164..00000000 --- a/tools/pharos-dashboard/src/booking/urls.py +++ /dev/null @@ -1,39 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -"""pharos_dashboard URL Configuration - -The `urlpatterns` list routes URLs to views. For more information please see: - https://docs.djangoproject.com/en/1.10/topics/http/urls/ -Examples: -Function views - 1. Add an import: from my_app import views - 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') -Class-based views - 1. Add an import: from other_app.views import Home - 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') -Including another URLconf - 1. Import the include() function: from django.conf.urls import url, include - 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) -""" -from django.conf.urls import url - -from booking.views import * - -urlpatterns = [ - url(r'^(?P<resource_id>[0-9]+)/$', BookingFormView.as_view(), name='create'), - url(r'^(?P<resource_id>[0-9]+)/bookings_json/$', ResourceBookingsJSON.as_view(), - name='bookings_json'), - - url(r'^detail/$', BookingView.as_view(), name='detail_prefix'), - url(r'^detail/(?P<booking_id>[0-9]+)/$', BookingView.as_view(), name='detail'), - - url(r'^list/$', BookingListView.as_view(), name='list') -] diff --git a/tools/pharos-dashboard/src/booking/views.py b/tools/pharos-dashboard/src/booking/views.py deleted file mode 100644 index 6fdca0e0..00000000 --- a/tools/pharos-dashboard/src/booking/views.py +++ /dev/null @@ -1,122 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -from django.conf import settings -from django.contrib import messages -from django.contrib.auth.mixins import LoginRequiredMixin -from django.http import JsonResponse -from django.shortcuts import get_object_or_404 -from django.urls import reverse -from django.utils import timezone -from django.views import View -from django.views.generic import FormView -from django.views.generic import TemplateView -from jira import JIRAError - -from account.jira_util import get_jira -from booking.forms import BookingForm -from booking.models import Booking -from dashboard.models import Resource - - -def create_jira_ticket(user, booking): - jira = get_jira(user) - issue_dict = { - 'project': 'PHAROS', - 'summary': str(booking.resource) + ': Access Request', - 'description': booking.purpose, - 'issuetype': {'name': 'Task'}, - 'components': [{'name': 'POD Access Request'}], - 'assignee': {'name': booking.resource.owner.username} - } - issue = jira.create_issue(fields=issue_dict) - jira.add_attachment(issue, user.userprofile.pgp_public_key) - jira.add_attachment(issue, user.userprofile.ssh_public_key) - booking.jira_issue_id = issue.id - booking.save() - - -class BookingFormView(FormView): - template_name = "booking/booking_calendar.html" - form_class = BookingForm - - def dispatch(self, request, *args, **kwargs): - self.resource = get_object_or_404(Resource, id=self.kwargs['resource_id']) - return super(BookingFormView, self).dispatch(request, *args, **kwargs) - - def get_context_data(self, **kwargs): - title = 'Booking: ' + self.resource.name - context = super(BookingFormView, self).get_context_data(**kwargs) - context.update({'title': title, 'resource': self.resource}) - return context - - def get_success_url(self): - return reverse('booking:create', kwargs=self.kwargs) - - def form_valid(self, form): - if not self.request.user.is_authenticated: - messages.add_message(self.request, messages.ERROR, - 'You need to be logged in to book a Pod.') - return super(BookingFormView, self).form_invalid(form) - - user = self.request.user - booking = Booking(start=form.cleaned_data['start'], - end=form.cleaned_data['end'], - purpose=form.cleaned_data['purpose'], - installer=form.cleaned_data['installer'], - scenario=form.cleaned_data['scenario'], - resource=self.resource, user=user) - try: - booking.save() - except ValueError as err: - messages.add_message(self.request, messages.ERROR, err) - return super(BookingFormView, self).form_invalid(form) - try: - if settings.CREATE_JIRA_TICKET: - create_jira_ticket(user, booking) - except JIRAError: - messages.add_message(self.request, messages.ERROR, 'Failed to create Jira Ticket. ' - 'Please check your Jira ' - 'permissions.') - booking.delete() - return super(BookingFormView, self).form_invalid(form) - messages.add_message(self.request, messages.SUCCESS, 'Booking saved') - return super(BookingFormView, self).form_valid(form) - - -class BookingView(TemplateView): - template_name = "booking/booking_detail.html" - - def get_context_data(self, **kwargs): - booking = get_object_or_404(Booking, id=self.kwargs['booking_id']) - title = 'Booking Details' - context = super(BookingView, self).get_context_data(**kwargs) - context.update({'title': title, 'booking': booking}) - return context - - -class BookingListView(TemplateView): - template_name = "booking/booking_list.html" - - def get_context_data(self, **kwargs): - bookings = Booking.objects.filter(end__gte=timezone.now()) - title = 'Search Booking' - context = super(BookingListView, self).get_context_data(**kwargs) - context.update({'title': title, 'bookings': bookings}) - return context - - -class ResourceBookingsJSON(View): - def get(self, request, *args, **kwargs): - resource = get_object_or_404(Resource, id=self.kwargs['resource_id']) - bookings = resource.booking_set.get_queryset().values('id', 'start', 'end', 'purpose', - 'jira_issue_status', - 'installer__name', 'scenario__name') - return JsonResponse({'bookings': list(bookings)}) diff --git a/tools/pharos-dashboard/src/dashboard/__init__.py b/tools/pharos-dashboard/src/dashboard/__init__.py deleted file mode 100644 index b5914ce7..00000000 --- a/tools/pharos-dashboard/src/dashboard/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - diff --git a/tools/pharos-dashboard/src/dashboard/admin.py b/tools/pharos-dashboard/src/dashboard/admin.py deleted file mode 100644 index 0bfdef8f..00000000 --- a/tools/pharos-dashboard/src/dashboard/admin.py +++ /dev/null @@ -1,20 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -from django.contrib import admin - -from dashboard.models import * - -admin.site.site_header = "Pharos Dashboard Administration" -admin.site.site_title = "Pharos Dashboard" - -admin.site.register(Resource) -admin.site.register(Server) -admin.site.register(ResourceStatus) diff --git a/tools/pharos-dashboard/src/dashboard/apps.py b/tools/pharos-dashboard/src/dashboard/apps.py deleted file mode 100644 index e0c4f442..00000000 --- a/tools/pharos-dashboard/src/dashboard/apps.py +++ /dev/null @@ -1,15 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -from django.apps import AppConfig - - -class DashboardConfig(AppConfig): - name = 'dashboard' diff --git a/tools/pharos-dashboard/src/dashboard/fixtures/dashboard.json b/tools/pharos-dashboard/src/dashboard/fixtures/dashboard.json deleted file mode 100644 index f0ac3b2f..00000000 --- a/tools/pharos-dashboard/src/dashboard/fixtures/dashboard.json +++ /dev/null @@ -1,164 +0,0 @@ -[ -{ - "model": "dashboard.resource", - "pk": 1, - "fields": { - "name": "Linux Foundation POD 1", - "description": "Some description", - "url": "https://wiki.opnfv.org/display/pharos/Lf+Lab" - } -}, -{ - "model": "dashboard.resource", - "pk": 2, - "fields": { - "name": "Linux Foundation POD 2", - "description": "Some description", - "url": "https://wiki.opnfv.org/display/pharos/Lf+Lab" - } -}, -{ - "model": "dashboard.resource", - "pk": 3, - "fields": { - "name": "Ericsson POD 2", - "description": "Some description", - "url": "https://wiki.opnfv.org/display/pharos/Ericsson+Hosting+and+Request+Process" - } -}, -{ - "model": "dashboard.resource", - "pk": 4, - "fields": { - "name": "Intel POD 2", - "description": "Some description", - "url": "https://wiki.opnfv.org/display/pharos/Intel+Pod2" - } -}, -{ - "model": "dashboard.resource", - "pk": 5, - "fields": { - "name": "Intel POD 5", - "description": "Some description", - "url": "https://wiki.opnfv.org/display/pharos/Intel+Pod5" - } -}, -{ - "model": "dashboard.resource", - "pk": 6, - "fields": { - "name": "Intel POD 6", - "description": "Some description", - "url": "https://wiki.opnfv.org/display/pharos/Intel+Pod6" - } -}, -{ - "model": "dashboard.resource", - "pk": 7, - "fields": { - "name": "Intel POD 8", - "description": "Some description", - "url": "https://wiki.opnfv.org/display/pharos/Intel+Pod8" - } -}, -{ - "model": "dashboard.resource", - "pk": 8, - "fields": { - "name": "Huawei POD 1", - "description": "Some description", - "url": "https://wiki.opnfv.org/display/pharos/Huawei+Hosting" - } -}, -{ - "model": "dashboard.resource", - "pk": 9, - "fields": { - "name": "Intel POD 3", - "description": "Some description", - "url": "https://wiki.opnfv.org/display/pharos/Intel+Pod3" - } -}, -{ - "model": "dashboard.resource", - "pk": 10, - "fields": { - "name": "Dell POD 1", - "description": "Some description", - "url": "https://wiki.opnfv.org/display/pharos/Dell+Hosting" - } -}, -{ - "model": "dashboard.resource", - "pk": 11, - "fields": { - "name": "Dell POD 2", - "description": "Some description", - "url": "https://wiki.opnfv.org/display/pharos/Dell+Hosting" - } -}, -{ - "model": "dashboard.resource", - "pk": 12, - "fields": { - "name": "Orange POD 2", - "description": "Some description", - "url": "https://wiki.opnfv.org/display/pharos/Opnfv-orange-pod2" - } -}, -{ - "model": "dashboard.resource", - "pk": 13, - "fields": { - "name": "Arm POD 1", - "description": "Some description", - "url": "https://wiki.opnfv.org/display/pharos/Enea-pharos-lab" - } -}, -{ - "model": "dashboard.resource", - "pk": 14, - "fields": { - "name": "Ericsson POD 1", - "description": "Some description", - "url": "https://wiki.opnfv.org/display/pharos/Ericsson+Hosting+and+Request+Process" - } -}, -{ - "model": "dashboard.resource", - "pk": 15, - "fields": { - "name": "Huawei POD 2", - "description": "Some description", - "url": "https://wiki.opnfv.org/display/pharos/Huawei+Hosting" - } -}, -{ - "model": "dashboard.resource", - "pk": 16, - "fields": { - "name": "Huawei POD 3", - "description": "Some description", - "url": "https://wiki.opnfv.org/display/pharos/Huawei+Hosting" - } -}, -{ - "model": "dashboard.resource", - "pk": 17, - "fields": { - "name": "Huawei POD 4", - "description": "Some description", - "url": "https://wiki.opnfv.org/display/pharos/Huawei+Hosting" - } -}, -{ - "model": "dashboard.resource", - "pk": 18, - "fields": { - "name": "Intel POD 9", - "description": "Some description", - "url": "https://wiki.opnfv.org/display/pharos/Intel+Pod9" - } -} -] diff --git a/tools/pharos-dashboard/src/dashboard/migrations/0001_initial.py b/tools/pharos-dashboard/src/dashboard/migrations/0001_initial.py deleted file mode 100644 index aaf3945f..00000000 --- a/tools/pharos-dashboard/src/dashboard/migrations/0001_initial.py +++ /dev/null @@ -1,64 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10 on 2016-11-03 13:33 -from __future__ import unicode_literals - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('jenkins', '0001_initial'), - ] - - operations = [ - migrations.CreateModel( - name='Resource', - fields=[ - ('id', models.AutoField(primary_key=True, serialize=False)), - ('name', models.CharField(max_length=100, unique=True)), - ('description', models.CharField(blank=True, max_length=300, null=True)), - ('url', models.CharField(blank=True, max_length=100, null=True)), - ('owner', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='user_lab_owner', to=settings.AUTH_USER_MODEL)), - ('slave', models.ForeignKey(null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='jenkins.JenkinsSlave')), - ('vpn_users', models.ManyToManyField(blank=True, related_name='user_vpn_users', to=settings.AUTH_USER_MODEL)), - ], - options={ - 'db_table': 'resource', - }, - ), - migrations.CreateModel( - name='ResourceStatus', - fields=[ - ('id', models.AutoField(primary_key=True, serialize=False)), - ('timestamp', models.DateTimeField(auto_now_add=True)), - ('type', models.CharField(max_length=20)), - ('title', models.CharField(max_length=50)), - ('content', models.CharField(max_length=5000)), - ('resource', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='dashboard.Resource')), - ], - options={ - 'db_table': 'resource_status', - }, - ), - migrations.CreateModel( - name='Server', - fields=[ - ('id', models.AutoField(primary_key=True, serialize=False)), - ('name', models.CharField(blank=True, max_length=100)), - ('model', models.CharField(blank=True, max_length=100)), - ('cpu', models.CharField(blank=True, max_length=100)), - ('ram', models.CharField(blank=True, max_length=100)), - ('storage', models.CharField(blank=True, max_length=100)), - ('resource', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='dashboard.Resource')), - ], - options={ - 'db_table': 'server', - }, - ), - ] diff --git a/tools/pharos-dashboard/src/dashboard/migrations/0002_auto_20170505_0815.py b/tools/pharos-dashboard/src/dashboard/migrations/0002_auto_20170505_0815.py deleted file mode 100644 index 4285b887..00000000 --- a/tools/pharos-dashboard/src/dashboard/migrations/0002_auto_20170505_0815.py +++ /dev/null @@ -1,42 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -# -*- coding: utf-8 -*- -# Generated by Django 1.10 on 2017-05-05 08:15 -from __future__ import unicode_literals - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('dashboard', '0001_initial'), - ] - - operations = [ - migrations.AddField( - model_name='resource', - name='dev_pod', - field=models.BooleanField(default=False), - ), - migrations.AlterField( - model_name='resource', - name='owner', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='user_lab_owner', to=settings.AUTH_USER_MODEL), - ), - migrations.AlterField( - model_name='resource', - name='slave', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='jenkins.JenkinsSlave'), - ), - ] diff --git a/tools/pharos-dashboard/src/dashboard/migrations/__init__.py b/tools/pharos-dashboard/src/dashboard/migrations/__init__.py deleted file mode 100644 index b5914ce7..00000000 --- a/tools/pharos-dashboard/src/dashboard/migrations/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - diff --git a/tools/pharos-dashboard/src/dashboard/models.py b/tools/pharos-dashboard/src/dashboard/models.py deleted file mode 100644 index 3de7db3d..00000000 --- a/tools/pharos-dashboard/src/dashboard/models.py +++ /dev/null @@ -1,95 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -from datetime import timedelta - -from django.contrib.auth.models import User -from django.db import models -from django.utils import timezone - -from jenkins.models import JenkinsSlave - - -class Resource(models.Model): - id = models.AutoField(primary_key=True) - name = models.CharField(max_length=100, unique=True) - description = models.CharField(max_length=300, blank=True, null=True) - url = models.CharField(max_length=100, blank=True, null=True) - owner = models.ForeignKey(User, related_name='user_lab_owner', null=True, blank=True) - vpn_users = models.ManyToManyField(User, related_name='user_vpn_users', blank=True) - slave = models.ForeignKey(JenkinsSlave, on_delete=models.DO_NOTHING, null=True, blank=True) - dev_pod = models.BooleanField(default=False) - - def get_booking_utilization(self, weeks): - """ - Return a dictionary containing the count of booked and free seconds for a resource in the - range [now,now + weeks] if weeks is positive, - or [now-weeks, now] if weeks is negative - """ - - length = timedelta(weeks=abs(weeks)) - now = timezone.now() - - start = now - end = now + length - if weeks < 0: - start = now - length - end = now - - bookings = self.booking_set.filter(start__lt=start + length, end__gt=start) - - booked_seconds = 0 - for booking in bookings: - booking_start = booking.start - booking_end = booking.end - if booking_start < start: - booking_start = start - if booking_end > end: - booking_end = start + length - total = booking_end - booking_start - booked_seconds += total.total_seconds() - - return {'booked_seconds': booked_seconds, - 'available_seconds': length.total_seconds() - booked_seconds} - - class Meta: - db_table = 'resource' - - def __str__(self): - return self.name - -class Server(models.Model): - id = models.AutoField(primary_key=True) - resource = models.ForeignKey(Resource, on_delete=models.CASCADE) - name = models.CharField(max_length=100, blank=True) - model = models.CharField(max_length=100, blank=True) - cpu = models.CharField(max_length=100, blank=True) - ram = models.CharField(max_length=100, blank=True) - storage = models.CharField(max_length=100, blank=True) - - class Meta: - db_table = 'server' - - def __str__(self): - return self.name - -class ResourceStatus(models.Model): - id = models.AutoField(primary_key=True) - resource = models.ForeignKey(Resource, on_delete=models.CASCADE) - timestamp = models.DateTimeField(auto_now_add=True) - type = models.CharField(max_length=20) - title = models.CharField(max_length=50) - content = models.CharField(max_length=5000) - - class Meta: - db_table = 'resource_status' - - def __str__(self): - return self.resource.name + ': ' + self.title + ' ' + str(self.timestamp) diff --git a/tools/pharos-dashboard/src/dashboard/tasks.py b/tools/pharos-dashboard/src/dashboard/tasks.py deleted file mode 100644 index c5ef5054..00000000 --- a/tools/pharos-dashboard/src/dashboard/tasks.py +++ /dev/null @@ -1,24 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -from datetime import timedelta - -from celery import shared_task -from django.utils import timezone - -from jenkins.models import JenkinsStatistic -from notification.models import BookingNotification - - -@shared_task -def database_cleanup(): - now = timezone.now() - JenkinsStatistic.objects.filter(timestamp__lt=now - timedelta(weeks=4)).delete() - BookingNotification.objects.filter(submit_time__lt=now - timedelta(weeks=4)).delete()
\ No newline at end of file diff --git a/tools/pharos-dashboard/src/dashboard/templatetags/__init__.py b/tools/pharos-dashboard/src/dashboard/templatetags/__init__.py deleted file mode 100644 index b5914ce7..00000000 --- a/tools/pharos-dashboard/src/dashboard/templatetags/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - diff --git a/tools/pharos-dashboard/src/dashboard/templatetags/jenkins_filters.py b/tools/pharos-dashboard/src/dashboard/templatetags/jenkins_filters.py deleted file mode 100644 index e7e14257..00000000 --- a/tools/pharos-dashboard/src/dashboard/templatetags/jenkins_filters.py +++ /dev/null @@ -1,38 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -from django.template.defaultfilters import register - - -@register.filter -def jenkins_job_color(job_result): - if job_result == 'SUCCESS': - return '#5cb85c' - if job_result == 'FAILURE': - return '#d9534f' - if job_result == 'UNSTABLE': - return '#EDD62B' - return '#646F73' # job is still building - - -@register.filter -def jenkins_status_color(slave_status): - if slave_status == 'offline': - return '#d9534f' - if slave_status == 'online': - return '#5cb85c' - if slave_status == 'online / idle': - return '#5bc0de' - - -@register.filter -def jenkins_job_blink(job_result): - if job_result == '': # job is still building - return 'class=blink_me' diff --git a/tools/pharos-dashboard/src/dashboard/templatetags/jira_filters.py b/tools/pharos-dashboard/src/dashboard/templatetags/jira_filters.py deleted file mode 100644 index 9a97c1d5..00000000 --- a/tools/pharos-dashboard/src/dashboard/templatetags/jira_filters.py +++ /dev/null @@ -1,17 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -from django.conf import settings -from django.template.defaultfilters import register - - -@register.filter -def jira_issue_url(issue): - return settings.JIRA_URL + '/browse/' + str(issue) diff --git a/tools/pharos-dashboard/src/dashboard/tests/__init__.py b/tools/pharos-dashboard/src/dashboard/tests/__init__.py deleted file mode 100644 index b5914ce7..00000000 --- a/tools/pharos-dashboard/src/dashboard/tests/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - diff --git a/tools/pharos-dashboard/src/dashboard/tests/test_models.py b/tools/pharos-dashboard/src/dashboard/tests/test_models.py deleted file mode 100644 index 3a3aeab1..00000000 --- a/tools/pharos-dashboard/src/dashboard/tests/test_models.py +++ /dev/null @@ -1,69 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -from datetime import timedelta -from math import ceil, floor - -from django.test import TestCase -from django.utils import timezone - -from booking.models import * -from dashboard.models import Resource -from jenkins.models import JenkinsSlave - - -class ResourceModelTestCase(TestCase): - def setUp(self): - self.slave = JenkinsSlave.objects.create(name='test', url='test') - self.owner = User.objects.create(username='owner') - - self.res1 = Resource.objects.create(name='res1', slave=self.slave, description='x', - url='x', owner=self.owner) - - def test_booking_utilization(self): - utilization = self.res1.get_booking_utilization(1) - self.assertTrue(utilization['booked_seconds'] == 0) - self.assertTrue(utilization['available_seconds'] == timedelta(weeks=1).total_seconds()) - - start = timezone.now() + timedelta(days=1) - end = start + timedelta(days=1) - booking = Booking.objects.create(start=start, end=end, purpose='test', resource=self.res1, - user=self.owner) - - utilization = self.res1.get_booking_utilization(1) - booked_seconds = timedelta(days=1).total_seconds() - self.assertEqual(utilization['booked_seconds'], booked_seconds) - - utilization = self.res1.get_booking_utilization(-1) - self.assertEqual(utilization['booked_seconds'], 0) - - booking.delete() - start = timezone.now() - timedelta(days=1) - end = start + timedelta(days=2) - booking = Booking.objects.create(start=start, end=end, purpose='test', resource=self.res1, - user=self.owner) - booked_seconds = self.res1.get_booking_utilization(1)['booked_seconds'] - # use ceil because a fraction of the booked time has already passed now - booked_seconds = ceil(booked_seconds) - self.assertEqual(booked_seconds, timedelta(days=1).total_seconds()) - - booking.delete() - start = timezone.now() + timedelta(days=6) - end = start + timedelta(days=2) - booking = Booking.objects.create(start=start, end=end, purpose='test', resource=self.res1, - user=self.owner) - booked_seconds = self.res1.get_booking_utilization(1)['booked_seconds'] - booked_seconds = floor(booked_seconds) - self.assertEqual(booked_seconds, timedelta(days=1).total_seconds()) - - - - - diff --git a/tools/pharos-dashboard/src/dashboard/tests/test_views.py b/tools/pharos-dashboard/src/dashboard/tests/test_views.py deleted file mode 100644 index f5e17c2a..00000000 --- a/tools/pharos-dashboard/src/dashboard/tests/test_views.py +++ /dev/null @@ -1,75 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -from django.test import TestCase -from django.urls import reverse - -from dashboard.models import Resource -from jenkins.models import JenkinsSlave - - -class DashboardViewTestCase(TestCase): - def setUp(self): - self.slave_active = JenkinsSlave.objects.create(name='slave_active', url='x', active=True) - self.slave_inactive = JenkinsSlave.objects.create(name='slave_inactive', url='x', - active=False) - self.res_active = Resource.objects.create(name='res_active', slave=self.slave_active, - description='x', url='x') - self.res_inactive = Resource.objects.create(name='res_inactive', slave=self.slave_inactive, - description='x', url='x') - - def test_booking_utilization_json(self): - url = reverse('dashboard:booking_utilization', kwargs={'resource_id': 0, 'weeks': 0}) - self.assertEqual(self.client.get(url).status_code, 404) - - url = reverse('dashboard:booking_utilization', kwargs={'resource_id': self.res_active.id, - 'weeks': 0}) - response = self.client.get(url) - self.assertEqual(response.status_code, 200) - self.assertContains(response, 'data') - - def test_jenkins_utilization_json(self): - url = reverse('dashboard:jenkins_utilization', kwargs={'resource_id': 0, 'weeks': 0}) - self.assertEqual(self.client.get(url).status_code, 404) - - url = reverse('dashboard:jenkins_utilization', kwargs={'resource_id': self.res_active.id, - 'weeks': 0}) - response = self.client.get(url) - self.assertEqual(response.status_code, 200) - self.assertContains(response, 'data') - - def test_jenkins_slaves_view(self): - url = reverse('dashboard:jenkins_slaves') - response = self.client.get(url) - self.assertEqual(response.status_code, 200) - self.assertIn(self.slave_active, response.context['slaves']) - self.assertNotIn(self.slave_inactive, response.context['slaves']) - - def test_ci_pods_view(self): - url = reverse('dashboard:ci_pods') - response = self.client.get(url) - self.assertEqual(response.status_code, 200) - self.assertEqual(len(response.context['ci_pods']), 0) - - self.slave_active.ci_slave = True - self.slave_inactive.ci_slave = True - self.slave_active.save() - self.slave_inactive.save() - - response = self.client.get(url) - self.assertIn(self.res_active, response.context['ci_pods']) - self.assertNotIn(self.res_inactive, response.context['ci_pods']) - - def test_dev_pods_view(self): - url = reverse('dashboard:dev_pods') - response = self.client.get(url) - self.assertEqual(response.status_code, 200) - self.assertEqual(len(response.context['dev_pods']), 0) - diff --git a/tools/pharos-dashboard/src/dashboard/urls.py b/tools/pharos-dashboard/src/dashboard/urls.py deleted file mode 100644 index 609e5d6f..00000000 --- a/tools/pharos-dashboard/src/dashboard/urls.py +++ /dev/null @@ -1,41 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -"""pharos_dashboard URL Configuration - -The `urlpatterns` list routes URLs to views. For more information please see: - https://docs.djangoproject.com/en/1.10/topics/http/urls/ -Examples: -Function views - 1. Add an import: from my_app import views - 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') -Class-based views - 1. Add an import: from other_app.views import Home - 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') -Including another URLconf - 1. Import the include() function: from django.conf.urls import url, include - 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) -""" -from django.conf.urls import url - -from dashboard.views import * - -urlpatterns = [ - url(r'^ci_pods/$', CIPodsView.as_view(), name='ci_pods'), - url(r'^dev_pods/$', DevelopmentPodsView.as_view(), name='dev_pods'), - url(r'^jenkins_slaves/$', JenkinsSlavesView.as_view(), name='jenkins_slaves'), - url(r'^resource/all/$', LabOwnerView.as_view(), name='resources'), - url(r'^resource/(?P<resource_id>[0-9]+)/$', ResourceView.as_view(), name='resource'), - url(r'^resource/(?P<resource_id>[0-9]+)/booking_utilization/(?P<weeks>-?\d+)/$', - BookingUtilizationJSON.as_view(), name='booking_utilization'), - url(r'^resource/(?P<resource_id>[0-9]+)/jenkins_utilization/(?P<weeks>-?\d+)/$', - JenkinsUtilizationJSON.as_view(), name='jenkins_utilization'), - url(r'^$', DevelopmentPodsView.as_view(), name="index"), -] diff --git a/tools/pharos-dashboard/src/dashboard/views.py b/tools/pharos-dashboard/src/dashboard/views.py deleted file mode 100644 index 62a9f830..00000000 --- a/tools/pharos-dashboard/src/dashboard/views.py +++ /dev/null @@ -1,141 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -from datetime import timedelta - -from django.http import JsonResponse -from django.shortcuts import get_object_or_404 -from django.utils import timezone -from django.views import View -from django.views.generic import TemplateView - -from booking.models import Booking -from dashboard.models import Resource -from jenkins.models import JenkinsSlave - - -class JenkinsSlavesView(TemplateView): - template_name = "dashboard/jenkins_slaves.html" - - def get_context_data(self, **kwargs): - slaves = JenkinsSlave.objects.filter(active=True) - context = super(JenkinsSlavesView, self).get_context_data(**kwargs) - context.update({'title': "Jenkins Slaves", 'slaves': slaves}) - return context - - -class CIPodsView(TemplateView): - template_name = "dashboard/ci_pods.html" - - def get_context_data(self, **kwargs): - ci_pods = Resource.objects.filter(slave__ci_slave=True, slave__active=True) - context = super(CIPodsView, self).get_context_data(**kwargs) - context.update({'title': "CI Pods", 'ci_pods': ci_pods}) - return context - - -class DevelopmentPodsView(TemplateView): - template_name = "dashboard/dev_pods.html" - - def get_context_data(self, **kwargs): - resources = Resource.objects.filter(dev_pod=True) - - bookings = Booking.objects.filter(start__lte=timezone.now()) - bookings = bookings.filter(end__gt=timezone.now()) - - dev_pods = [] - for resource in resources: - booking_utilization = resource.get_booking_utilization(weeks=4) - total = booking_utilization['booked_seconds'] + booking_utilization['available_seconds'] - try: - utilization_percentage = "%d%%" % (float(booking_utilization['booked_seconds']) / - total * 100) - except (ValueError, ZeroDivisionError): - return "" - - dev_pod = (resource, None, utilization_percentage) - for booking in bookings: - if booking.resource == resource: - dev_pod = (resource, booking, utilization_percentage) - dev_pods.append(dev_pod) - - context = super(DevelopmentPodsView, self).get_context_data(**kwargs) - context.update({'title': "Development Pods", 'dev_pods': dev_pods}) - return context - - -class ResourceView(TemplateView): - template_name = "dashboard/resource.html" - - def get_context_data(self, **kwargs): - resource = get_object_or_404(Resource, id=self.kwargs['resource_id']) - bookings = Booking.objects.filter(resource=resource, end__gt=timezone.now()) - context = super(ResourceView, self).get_context_data(**kwargs) - context.update({'title': str(resource), 'resource': resource, 'bookings': bookings}) - return context - - -class LabOwnerView(TemplateView): - template_name = "dashboard/resource_all.html" - - def get_context_data(self, **kwargs): - resources = Resource.objects.filter(slave__dev_pod=True, slave__active=True) - pods = [] - for resource in resources: - utilization = resource.slave.get_utilization(timedelta(days=7)) - bookings = Booking.objects.filter(resource=resource, end__gt=timezone.now()) - pods.append((resource, utilization, bookings)) - context = super(LabOwnerView, self).get_context_data(**kwargs) - context.update({'title': "Overview", 'pods': pods}) - return context - - -class BookingUtilizationJSON(View): - def get(self, request, *args, **kwargs): - resource = get_object_or_404(Resource, id=kwargs['resource_id']) - utilization = resource.get_booking_utilization(int(kwargs['weeks'])) - utilization = [ - { - 'label': 'Booked', - 'data': utilization['booked_seconds'], - 'color': '#d9534f' - }, - { - 'label': 'Available', - 'data': utilization['available_seconds'], - 'color': '#5cb85c' - }, - ] - return JsonResponse({'data': utilization}) - - -class JenkinsUtilizationJSON(View): - def get(self, request, *args, **kwargs): - resource = get_object_or_404(Resource, id=kwargs['resource_id']) - weeks = int(kwargs['weeks']) - utilization = resource.slave.get_utilization(timedelta(weeks=weeks)) - utilization = [ - { - 'label': 'Offline', - 'data': utilization['offline'], - 'color': '#d9534f' - }, - { - 'label': 'Online', - 'data': utilization['online'], - 'color': '#5cb85c' - }, - { - 'label': 'Idle', - 'data': utilization['idle'], - 'color': '#5bc0de' - }, - ] - return JsonResponse({'data': utilization}) diff --git a/tools/pharos-dashboard/src/jenkins/__init__.py b/tools/pharos-dashboard/src/jenkins/__init__.py deleted file mode 100644 index b5914ce7..00000000 --- a/tools/pharos-dashboard/src/jenkins/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - diff --git a/tools/pharos-dashboard/src/jenkins/adapter.py b/tools/pharos-dashboard/src/jenkins/adapter.py deleted file mode 100644 index edf502f6..00000000 --- a/tools/pharos-dashboard/src/jenkins/adapter.py +++ /dev/null @@ -1,134 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -import logging -import re - -import requests -from django.core.cache import cache - -logger = logging.getLogger(__name__) - -# TODO: implement caching decorator, cache get_* functions -def get_json(url): - if cache.get(url) is None: - try: - response = requests.get(url) - json = response.json() - cache.set(url, json, 180) # cache result for 180 seconds - return json - except requests.exceptions.RequestException as e: - logger.exception(e) - except ValueError as e: - logger.exception(e) - else: - return cache.get(url) - - -def get_all_slaves(): - url = "https://build.opnfv.org/ci/computer/api/json?tree=computer[displayName,offline,idle]" - json = get_json(url) - if json is not None: - return json['computer'] # return list of dictionaries - return [] - - -def get_slave(slavename): - slaves = get_all_slaves() - for slave in slaves: - if slave['displayName'] == slavename: - return slave - return {} - - -def get_ci_slaves(): - url = "https://build.opnfv.org/ci/label/ci-pod/api/json?tree=nodes[nodeName,offline,idle]" - json = get_json(url) - if json is not None: - return json['nodes'] - return [] - - -def get_all_jobs(): - url = "https://build.opnfv.org/ci/api/json?tree=jobs[displayName,url,lastBuild[fullDisplayName,building,builtOn,timestamp,result]]" - json = get_json(url) - if json is not None: - return json['jobs'] # return list of dictionaries - return [] - - -def get_jenkins_job(slavename): - jobs = get_all_jobs() - max_time = 0 - last_job = None - for job in jobs: - if job['lastBuild'] is not None: - if job['lastBuild']['builtOn'] == slavename: - if job['lastBuild']['building'] is True: - return job # return active build - if job['lastBuild']['timestamp'] > max_time: - last_job = job - max_time = job['lastBuild']['timestamp'] - return last_job - - -def is_ci_slave(slavename): - ci_slaves = get_ci_slaves() - for ci_slave in ci_slaves: - if ci_slave['nodeName'] == slavename: - return True - return False - - -def is_dev_pod(slavename): - if is_ci_slave(slavename): - return False - if slavename.find('pod') != -1: - return True - return False - - -def parse_job(job): - result = parse_job_string(job['lastBuild']['fullDisplayName']) - result['building'] = job['lastBuild']['building'] - result['result'] = '' - if not job['lastBuild']['building']: - result['result'] = job['lastBuild']['result'] - result['url'] = job['url'] - return result - - -def parse_job_string(full_displayname): - job = {} - job['scenario'] = '' - job['installer'] = '' - job['branch'] = '' - tokens = re.split(r'[ -]', full_displayname) - for i in range(len(tokens)): - if tokens[i] == 'os': - job['scenario'] = '-'.join(tokens[i: i + 4]) - elif tokens[i] in ['fuel', 'joid', 'apex', 'compass']: - job['installer'] = tokens[i] - elif tokens[i] in ['master', 'arno', 'brahmaputra', 'colorado']: - job['branch'] = tokens[i] - tokens = full_displayname.split(' ') - job['name'] = tokens[0] - return job - -def get_slave_url(slave): - return 'https://build.opnfv.org/ci/computer/' + slave['displayName'] - - -def get_slave_status(slave): - if not slave['offline'] and slave['idle']: - return 'online / idle' - if not slave['offline']: - return 'online' - return 'offline' diff --git a/tools/pharos-dashboard/src/jenkins/admin.py b/tools/pharos-dashboard/src/jenkins/admin.py deleted file mode 100644 index c4996702..00000000 --- a/tools/pharos-dashboard/src/jenkins/admin.py +++ /dev/null @@ -1,17 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -from django.conf import settings -from django.contrib import admin - -from jenkins.models import JenkinsSlave - -if settings.DEBUG: - admin.site.register(JenkinsSlave)
\ No newline at end of file diff --git a/tools/pharos-dashboard/src/jenkins/apps.py b/tools/pharos-dashboard/src/jenkins/apps.py deleted file mode 100644 index 41faf600..00000000 --- a/tools/pharos-dashboard/src/jenkins/apps.py +++ /dev/null @@ -1,15 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -from django.apps import AppConfig - - -class JenkinsConfig(AppConfig): - name = 'jenkins' diff --git a/tools/pharos-dashboard/src/jenkins/migrations/0001_initial.py b/tools/pharos-dashboard/src/jenkins/migrations/0001_initial.py deleted file mode 100644 index b1c78897..00000000 --- a/tools/pharos-dashboard/src/jenkins/migrations/0001_initial.py +++ /dev/null @@ -1,53 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10 on 2016-11-03 13:33 -from __future__ import unicode_literals - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - ] - - operations = [ - migrations.CreateModel( - name='JenkinsSlave', - fields=[ - ('id', models.AutoField(primary_key=True, serialize=False)), - ('name', models.CharField(max_length=100, unique=True)), - ('status', models.CharField(default='offline', max_length=30)), - ('url', models.CharField(max_length=1024)), - ('ci_slave', models.BooleanField(default=False)), - ('dev_pod', models.BooleanField(default=False)), - ('building', models.BooleanField(default=False)), - ('last_job_name', models.CharField(default='', max_length=1024)), - ('last_job_url', models.CharField(default='', max_length=1024)), - ('last_job_scenario', models.CharField(default='', max_length=50)), - ('last_job_branch', models.CharField(default='', max_length=50)), - ('last_job_installer', models.CharField(default='', max_length=50)), - ('last_job_result', models.CharField(default='', max_length=30)), - ('active', models.BooleanField(default=False)), - ], - options={ - 'db_table': 'jenkins_slave', - }, - ), - migrations.CreateModel( - name='JenkinsStatistic', - fields=[ - ('id', models.AutoField(primary_key=True, serialize=False)), - ('offline', models.BooleanField(default=False)), - ('idle', models.BooleanField(default=False)), - ('online', models.BooleanField(default=False)), - ('timestamp', models.DateTimeField(auto_now_add=True)), - ('slave', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='jenkins.JenkinsSlave')), - ], - options={ - 'db_table': 'jenkins_statistic', - }, - ), - ] diff --git a/tools/pharos-dashboard/src/jenkins/migrations/__init__.py b/tools/pharos-dashboard/src/jenkins/migrations/__init__.py deleted file mode 100644 index b5914ce7..00000000 --- a/tools/pharos-dashboard/src/jenkins/migrations/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - diff --git a/tools/pharos-dashboard/src/jenkins/models.py b/tools/pharos-dashboard/src/jenkins/models.py deleted file mode 100644 index 8254ff39..00000000 --- a/tools/pharos-dashboard/src/jenkins/models.py +++ /dev/null @@ -1,62 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -from django.db import models -from django.utils import timezone - - -class JenkinsSlave(models.Model): - id = models.AutoField(primary_key=True) - name = models.CharField(max_length=100, unique=True) - status = models.CharField(max_length=30, default='offline') - url = models.CharField(max_length=1024) - ci_slave = models.BooleanField(default=False) - dev_pod = models.BooleanField(default=False) - - building = models.BooleanField(default=False) - - last_job_name = models.CharField(max_length=1024, default='') - last_job_url = models.CharField(max_length=1024, default='') - last_job_scenario = models.CharField(max_length=50, default='') - last_job_branch = models.CharField(max_length=50, default='') - last_job_installer = models.CharField(max_length=50, default='') - last_job_result = models.CharField(max_length=30, default='') - - active = models.BooleanField(default=False) - - def get_utilization(self, timedelta): - """ - Return a dictionary containing the count of idle, online and offline measurements in the time from - now-timedelta to now - """ - utilization = {'idle': 0, 'online': 0, 'offline': 0} - statistics = self.jenkinsstatistic_set.filter(timestamp__gte=timezone.now() - timedelta) - utilization['idle'] = statistics.filter(idle=True).count() - utilization['online'] = statistics.filter(online=True).count() - utilization['offline'] = statistics.filter(offline=True).count() - return utilization - - class Meta: - db_table = 'jenkins_slave' - - def __str__(self): - return self.name - - -class JenkinsStatistic(models.Model): - id = models.AutoField(primary_key=True) - slave = models.ForeignKey(JenkinsSlave, on_delete=models.CASCADE) - offline = models.BooleanField(default=False) - idle = models.BooleanField(default=False) - online = models.BooleanField(default=False) - timestamp = models.DateTimeField(auto_now_add=True) - - class Meta: - db_table = 'jenkins_statistic' diff --git a/tools/pharos-dashboard/src/jenkins/tasks.py b/tools/pharos-dashboard/src/jenkins/tasks.py deleted file mode 100644 index ea986c1f..00000000 --- a/tools/pharos-dashboard/src/jenkins/tasks.py +++ /dev/null @@ -1,64 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -from celery import shared_task - -from dashboard.models import Resource -from jenkins.models import JenkinsSlave, JenkinsStatistic -from .adapter import * - - -@shared_task -def sync_jenkins(): - update_jenkins_slaves() - - -def update_jenkins_slaves(): - JenkinsSlave.objects.all().update(active=False) - - jenkins_slaves = get_all_slaves() - for slave in jenkins_slaves: - jenkins_slave, created = JenkinsSlave.objects.get_or_create(name=slave['displayName'], - url=get_slave_url(slave)) - jenkins_slave.active = True - jenkins_slave.ci_slave = is_ci_slave(slave['displayName']) - jenkins_slave.dev_pod = is_dev_pod(slave['displayName']) - jenkins_slave.status = get_slave_status(slave) - - # if this is a new slave and a pod, check if there is a resource for it, create one if not - if created and 'pod' in slave['displayName']: - # parse resource name from slave name - # naming example: orange-pod1, resource name: Orange POD 1 - tokens = slave['displayName'].split('-') - name = tokens[0].capitalize() + ' POD '# company name - name += tokens[1][3:] # remove 'pod' - resource, created = Resource.objects.get_or_create(name=name) - resource.slave = jenkins_slave - resource.save() - - last_job = get_jenkins_job(jenkins_slave.name) - if last_job is not None: - last_job = parse_job(last_job) - jenkins_slave.last_job_name = last_job['name'] - jenkins_slave.last_job_url = last_job['url'] - jenkins_slave.last_job_scenario = last_job['scenario'] - jenkins_slave.last_job_branch = last_job['branch'] - jenkins_slave.last_job_installer = last_job['installer'] - jenkins_slave.last_job_result = last_job['result'] - jenkins_slave.save() - - jenkins_statistic = JenkinsStatistic(slave=jenkins_slave) - if jenkins_slave.status == 'online' or jenkins_slave.status == 'building': - jenkins_statistic.online = True - if jenkins_slave.status == 'offline': - jenkins_statistic.offline = True - if jenkins_slave.status == 'online / idle': - jenkins_statistic.idle = True - jenkins_statistic.save() diff --git a/tools/pharos-dashboard/src/jenkins/tests.py b/tools/pharos-dashboard/src/jenkins/tests.py deleted file mode 100644 index 3723cd38..00000000 --- a/tools/pharos-dashboard/src/jenkins/tests.py +++ /dev/null @@ -1,129 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -from datetime import timedelta -from unittest import TestCase - -import jenkins.adapter as jenkins -from jenkins.models import * - - -# Tests that the data we get with the jenkinsadapter contains all the -# data we need. These test will fail if; -# - there is no internet connection -# - the opnfv jenkins url has changed -# - the jenkins api has changed -# - jenkins is not set up / there is no data -class JenkinsAdapterTestCase(TestCase): - def test_get_all_slaves(self): - slaves = jenkins.get_all_slaves() - self.assertTrue(len(slaves) > 0) - for slave in slaves: - self.assertTrue('displayName' in slave) - self.assertTrue('idle' in slave) - self.assertTrue('offline' in slave) - - def test_get_slave(self): - slaves = jenkins.get_all_slaves() - self.assertEqual(slaves[0], jenkins.get_slave(slaves[0]['displayName'])) - self.assertEqual({}, jenkins.get_slave('098f6bcd4621d373cade4e832627b4f6')) - - def test_get_ci_slaves(self): - slaves = jenkins.get_ci_slaves() - self.assertTrue(len(slaves) > 0) - for slave in slaves: - self.assertTrue('nodeName' in slave) - - def test_get_jenkins_job(self): - slaves = jenkins.get_ci_slaves() - job = None - for slave in slaves: - job = jenkins.get_jenkins_job(slave['nodeName']) - if job is not None: - break - # We need to test at least one job - self.assertNotEqual(job, None) - - def test_get_all_jobs(self): - jobs = jenkins.get_all_jobs() - lastBuild = False - self.assertTrue(len(jobs) > 0) - for job in jobs: - self.assertTrue('displayName' in job) - self.assertTrue('url' in job) - self.assertTrue('lastBuild' in job) - if job['lastBuild'] is not None: - lastBuild = True - self.assertTrue('building' in job['lastBuild']) - self.assertTrue('fullDisplayName' in job['lastBuild']) - self.assertTrue('result' in job['lastBuild']) - self.assertTrue('timestamp' in job['lastBuild']) - self.assertTrue('builtOn' in job['lastBuild']) - self.assertTrue(lastBuild) - - def test_parse_job(self): - job = { - "displayName": "apex-deploy-baremetal-os-nosdn-fdio-noha-colorado", - "url": "https://build.opnfv.org/ci/job/apex-deploy-baremetal-os-nosdn-fdio-noha-colorado/", - "lastBuild": { - "building": False, - "fullDisplayName": "apex-deploy-baremetal-os-nosdn-fdio-noha-colorado #37", - "result": "SUCCESS", - "timestamp": 1476283629917, - "builtOn": "lf-pod1" - } - } - - job = jenkins.parse_job(job) - self.assertEqual(job['scenario'], 'os-nosdn-fdio-noha') - self.assertEqual(job['installer'], 'apex') - self.assertEqual(job['branch'], 'colorado') - self.assertEqual(job['result'], 'SUCCESS') - self.assertEqual(job['building'], False) - self.assertEqual(job['url'], - "https://build.opnfv.org/ci/job/apex-deploy-baremetal-os-nosdn-fdio-noha-colorado/") - self.assertEqual(job['name'], - 'apex-deploy-baremetal-os-nosdn-fdio-noha-colorado') - - def test_get_slave_status(self): - slave = { - 'offline': True, - 'idle': False - } - self.assertEqual(jenkins.get_slave_status(slave), 'offline') - slave = { - 'offline': False, - 'idle': False - } - self.assertEqual(jenkins.get_slave_status(slave), 'online') - slave = { - 'offline': False, - 'idle': True - } - self.assertEqual(jenkins.get_slave_status(slave), 'online / idle') - - -class JenkinsModelTestCase(TestCase): - def test_get_utilization(self): - jenkins_slave = JenkinsSlave.objects.create(name='test', status='offline', url='') - utilization = jenkins_slave.get_utilization(timedelta(weeks=1)) - self.assertEqual(utilization['idle'], 0) - self.assertEqual(utilization['offline'], 0) - self.assertEqual(utilization['online'], 0) - - for i in range(10): - JenkinsStatistic.objects.create(slave=jenkins_slave, - offline=True, idle=True, - online=True) - - utilization = jenkins_slave.get_utilization(timedelta(weeks=1)) - self.assertEqual(utilization['idle'], 10) - self.assertEqual(utilization['offline'], 10) - self.assertEqual(utilization['online'], 10) diff --git a/tools/pharos-dashboard/src/manage.py b/tools/pharos-dashboard/src/manage.py deleted file mode 100644 index 80c496f3..00000000 --- a/tools/pharos-dashboard/src/manage.py +++ /dev/null @@ -1,32 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -#!/usr/bin/env python -import os -import sys - -if __name__ == "__main__": - os.environ.setdefault("DJANGO_SETTINGS_MODULE", "pharos_dashboard.settings") - try: - from django.core.management import execute_from_command_line - except ImportError: - # The above import may fail for some other reason. Ensure that the - # issue is really that Django is missing to avoid masking other - # exceptions on Python 2. - try: - import django - except ImportError: - raise ImportError( - "Couldn't import Django. Are you sure it's installed and " - "available on your PYTHONPATH environment variable? Did you " - "forget to activate a virtual environment?" - ) - raise - execute_from_command_line(sys.argv) diff --git a/tools/pharos-dashboard/src/notification/__init__.py b/tools/pharos-dashboard/src/notification/__init__.py deleted file mode 100644 index 37dcbddf..00000000 --- a/tools/pharos-dashboard/src/notification/__init__.py +++ /dev/null @@ -1,11 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -default_app_config = 'notification.apps.NotificationConfig'
\ No newline at end of file diff --git a/tools/pharos-dashboard/src/notification/admin.py b/tools/pharos-dashboard/src/notification/admin.py deleted file mode 100644 index bcaa1ab7..00000000 --- a/tools/pharos-dashboard/src/notification/admin.py +++ /dev/null @@ -1,17 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -from django.conf import settings -from django.contrib import admin - -from notification.models import BookingNotification - -if settings.DEBUG: - admin.site.register(BookingNotification)
\ No newline at end of file diff --git a/tools/pharos-dashboard/src/notification/apps.py b/tools/pharos-dashboard/src/notification/apps.py deleted file mode 100644 index 2de22c4e..00000000 --- a/tools/pharos-dashboard/src/notification/apps.py +++ /dev/null @@ -1,18 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -from django.apps import AppConfig - - -class NotificationConfig(AppConfig): - name = 'notification' - - def ready(self): - import notification.signals #noqa
\ No newline at end of file diff --git a/tools/pharos-dashboard/src/notification/migrations/0001_initial.py b/tools/pharos-dashboard/src/notification/migrations/0001_initial.py deleted file mode 100644 index 8b8414e6..00000000 --- a/tools/pharos-dashboard/src/notification/migrations/0001_initial.py +++ /dev/null @@ -1,28 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10 on 2016-11-03 13:33 -from __future__ import unicode_literals - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - ('booking', '0001_initial'), - ] - - operations = [ - migrations.CreateModel( - name='BookingNotification', - fields=[ - ('id', models.AutoField(primary_key=True, serialize=False)), - ('type', models.CharField(max_length=100)), - ('submit_time', models.DateTimeField()), - ('submitted', models.BooleanField(default=False)), - ('booking', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='booking.Booking')), - ], - ), - ] diff --git a/tools/pharos-dashboard/src/notification/migrations/__init__.py b/tools/pharos-dashboard/src/notification/migrations/__init__.py deleted file mode 100644 index b5914ce7..00000000 --- a/tools/pharos-dashboard/src/notification/migrations/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - diff --git a/tools/pharos-dashboard/src/notification/models.py b/tools/pharos-dashboard/src/notification/models.py deleted file mode 100644 index 89b30234..00000000 --- a/tools/pharos-dashboard/src/notification/models.py +++ /dev/null @@ -1,33 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -from django.db import models - -class BookingNotification(models.Model): - id = models.AutoField(primary_key=True) - type = models.CharField(max_length=100) - booking = models.ForeignKey('booking.Booking', on_delete=models.CASCADE) - submit_time = models.DateTimeField() - submitted = models.BooleanField(default=False) - - def get_content(self): - return { - 'resource_id': self.booking.resource.id, - 'booking_id': self.booking.id, - 'user': self.booking.user.username, - 'user_id': self.booking.user.id, - } - - def save(self, *args, **kwargs): - notifications = self.booking.bookingnotification_set.filter(type=self.type).exclude( - id=self.id) - #if notifications.count() > 0: - # raise ValueError('Doubled Notification') - return super(BookingNotification, self).save(*args, **kwargs) diff --git a/tools/pharos-dashboard/src/notification/signals.py b/tools/pharos-dashboard/src/notification/signals.py deleted file mode 100644 index 936c25ba..00000000 --- a/tools/pharos-dashboard/src/notification/signals.py +++ /dev/null @@ -1,25 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -from django.db.models.signals import post_save -from django.dispatch import receiver - -from booking.models import Booking -from notification.models import BookingNotification - - -@receiver(post_save, sender=Booking) -def booking_notification_handler(sender, instance, **kwargs): - BookingNotification.objects.update_or_create( - booking=instance, type='booking_start', defaults={'submit_time': instance.start} - ) - BookingNotification.objects.update_or_create( - booking=instance, type='booking_end', defaults={'submit_time': instance.end} - )
\ No newline at end of file diff --git a/tools/pharos-dashboard/src/notification/tasks.py b/tools/pharos-dashboard/src/notification/tasks.py deleted file mode 100644 index 7f737625..00000000 --- a/tools/pharos-dashboard/src/notification/tasks.py +++ /dev/null @@ -1,49 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -import os -import sys -from datetime import timedelta - -from celery import shared_task -from django.conf import settings -from django.utils import timezone - -from notification.models import BookingNotification - -# this adds the top level directory to the python path, this is needed so that we can access the -# notification library -sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..')) - -from dashboard_notification.notification import Notification, Message - - -@shared_task -def send_booking_notifications(): - with Notification(dashboard_url=settings.RABBITMQ_URL, user=settings.RABBITMQ_USER, password=settings.RABBITMQ_PASSWORD) as messaging: - now = timezone.now() - notifications = BookingNotification.objects.filter(submitted=False, - submit_time__gt=now - timedelta(minutes=1), - submit_time__lt=now + timedelta(minutes=5)) - for notification in notifications: - message = Message(type=notification.type, topic=notification.booking.resource.name, - content=notification.get_content()) - messaging.send(message) - notification.submitted = True - notification.save() - -@shared_task -def notification_debug(): - with Notification(dashboard_url=settings.RABBITMQ_URL) as messaging: - notifications = BookingNotification.objects.all() - for notification in notifications: - message = Message(type=notification.type, topic=notification.booking.resource.name, - content=notification.get_content()) - messaging.send(message) diff --git a/tools/pharos-dashboard/src/notification/tests.py b/tools/pharos-dashboard/src/notification/tests.py deleted file mode 100644 index 9df9aa60..00000000 --- a/tools/pharos-dashboard/src/notification/tests.py +++ /dev/null @@ -1,41 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -from datetime import timedelta -from unittest import TestCase - -from django.contrib.auth.models import User -from django.utils import timezone - -from booking.models import Booking -from dashboard.models import Resource -from jenkins.models import JenkinsSlave -from notification.models import * - - -class JenkinsModelTestCase(TestCase): - def setUp(self): - self.slave = JenkinsSlave.objects.create(name='test1', url='test') - self.res1 = Resource.objects.create(name='res1', slave=self.slave, description='x', - url='x') - self.user1 = User.objects.create(username='user1') - - start = timezone.now() - end = start + timedelta(days=1) - self.booking = Booking.objects.create(start=start, end=end, purpose='test', - resource=self.res1, user=self.user1) - - def test_booking_notification(self): - BookingNotification.objects.create(type='test', booking=self.booking, - submit_time=timezone.now()) - - self.assertRaises(ValueError, BookingNotification.objects.create, type='test', - booking=self.booking, - submit_time=timezone.now()) diff --git a/tools/pharos-dashboard/src/pharos_dashboard/__init__.py b/tools/pharos-dashboard/src/pharos_dashboard/__init__.py deleted file mode 100644 index f104c4db..00000000 --- a/tools/pharos-dashboard/src/pharos_dashboard/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -# This will make sure the app is always imported when -# Django starts so that shared_task will use this app. -from .celery import app as celery_app # noqa diff --git a/tools/pharos-dashboard/src/pharos_dashboard/celery.py b/tools/pharos-dashboard/src/pharos_dashboard/celery.py deleted file mode 100644 index f60f2433..00000000 --- a/tools/pharos-dashboard/src/pharos_dashboard/celery.py +++ /dev/null @@ -1,30 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -import os - -from celery import Celery - -# set the default Django settings module for the 'celery' program. -os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'pharos_dashboard.settings') - -from django.conf import settings # noqa - -app = Celery('pharos_dashboard') - -# Using a string here means the worker will not have to -# pickle the object when using Windows. -app.config_from_object('django.conf:settings') -app.autodiscover_tasks(lambda: settings.INSTALLED_APPS) - - -@app.task(bind=True) -def debug_task(self): - print('Request: {0!r}'.format(self.request))
\ No newline at end of file diff --git a/tools/pharos-dashboard/src/pharos_dashboard/settings.py b/tools/pharos-dashboard/src/pharos_dashboard/settings.py deleted file mode 100644 index 546b174e..00000000 --- a/tools/pharos-dashboard/src/pharos_dashboard/settings.py +++ /dev/null @@ -1,184 +0,0 @@ -import os -from datetime import timedelta - -# Build paths inside the project like this: os.path.join(BASE_DIR, ...) -BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - -# SECURITY WARNING: don't run with debug turned on in production! -DEBUG = True - -# Application definition - -INSTALLED_APPS = [ - 'dashboard', - 'booking', - 'account', - 'jenkins', - 'notification', - 'django.contrib.admin', - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.messages', - 'django.contrib.staticfiles', - 'django.contrib.humanize', - 'bootstrap3', - 'crispy_forms', - 'rest_framework', - 'rest_framework.authtoken', -] - -MIDDLEWARE = [ - 'django.middleware.security.SecurityMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.common.CommonMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'django.middleware.clickjacking.XFrameOptionsMiddleware', - 'account.middleware.TimezoneMiddleware', -] - -ROOT_URLCONF = 'pharos_dashboard.urls' - -TEMPLATES = [ - { - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': [os.path.join(BASE_DIR, 'templates')] - , - 'APP_DIRS': True, - 'OPTIONS': { - 'context_processors': [ - 'django.template.context_processors.debug', - 'django.template.context_processors.request', - 'django.contrib.auth.context_processors.auth', - 'django.contrib.messages.context_processors.messages', - ], - }, - }, -] - -WSGI_APPLICATION = 'pharos_dashboard.wsgi.application' - -# Password validation -# https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators - -AUTH_PASSWORD_VALIDATORS = [ - { - 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', - }, - { - 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', - }, - { - 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', - }, - { - 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', - }, -] - -# Internationalization -# https://docs.djangoproject.com/en/1.10/topics/i18n/ - -LANGUAGE_CODE = 'en-us' - -TIME_ZONE = 'UTC' - -USE_I18N = True - -USE_L10N = True - -USE_TZ = True - -# Static files (CSS, JavaScript, Images) -# https://docs.djangoproject.com/en/1.10/howto/static-files/ -MEDIA_URL = '/media/' -STATIC_URL = '/static/' - -# Static files (CSS, JavaScript, Images) -# https://docs.djangoproject.com/en/1.10/howto/static-files/ -STATICFILES_DIRS = [ - os.path.join(BASE_DIR, "static"), -] - -LOGIN_REDIRECT_URL = '/' - -# SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = os.environ['SECRET_KEY'] - -BOOTSTRAP3 = { - 'set_placeholder': False, -} - -ALLOWED_HOSTS = ['*'] - -# Database -# https://docs.djangoproject.com/en/1.10/ref/settings/#databases -DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.postgresql', - 'NAME': os.environ['DB_NAME'], - 'USER': os.environ['DB_USER'], - 'PASSWORD': os.environ['DB_PASS'], - 'HOST': os.environ['DB_SERVICE'], - 'PORT': os.environ['DB_PORT'] - } -} - - -# Rest API Settings -REST_FRAMEWORK = { - 'DEFAULT_PERMISSION_CLASSES': [ - 'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly' - ], - 'DEFAULT_FILTER_BACKENDS': ('rest_framework.filters.DjangoFilterBackend',), - 'DEFAULT_AUTHENTICATION_CLASSES': ( - 'rest_framework.authentication.SessionAuthentication', - 'rest_framework.authentication.TokenAuthentication', - ) -} - -MEDIA_ROOT = '/media' -STATIC_ROOT = '/static' - -# Jira Settings -CREATE_JIRA_TICKET = False - -JIRA_URL = os.environ['JIRA_URL'] - -JIRA_USER_NAME = os.environ['JIRA_USER_NAME'] -JIRA_USER_PASSWORD = os.environ['JIRA_USER_PASSWORD'] - -OAUTH_CONSUMER_KEY = os.environ['OAUTH_CONSUMER_KEY'] -OAUTH_CONSUMER_SECRET = os.environ['OAUTH_CONSUMER_SECRET'] - -OAUTH_REQUEST_TOKEN_URL = JIRA_URL + '/plugins/servlet/oauth/request-token' -OAUTH_ACCESS_TOKEN_URL = JIRA_URL + '/plugins/servlet/oauth/access-token' -OAUTH_AUTHORIZE_URL = JIRA_URL + '/plugins/servlet/oauth/authorize' - -OAUTH_CALLBACK_URL = os.environ['DASHBOARD_URL'] + '/accounts/authenticated' - -# Celery Settings -CELERY_TIMEZONE = 'UTC' - -RABBITMQ_URL = 'rabbitmq' -RABBITMQ_USER = os.environ['RABBITMQ_USER'] -RABBITMQ_PASSWORD = os.environ['RABBITMQ_PASSWORD'] - -BROKER_URL = 'amqp://' + RABBITMQ_USER + ':' + RABBITMQ_PASSWORD + '@rabbitmq:5672//' - -CELERYBEAT_SCHEDULE = { - 'sync-jenkins': { - 'task': 'jenkins.tasks.sync_jenkins', - 'schedule': timedelta(minutes=5) - }, - 'send-booking-notifications': { - 'task': 'notification.tasks.send_booking_notifications', - 'schedule': timedelta(minutes=5) - }, - 'clean-database': { - 'task': 'dashboard.tasks.database_cleanup', - 'schedule': timedelta(hours=24) - }, -} diff --git a/tools/pharos-dashboard/src/pharos_dashboard/urls.py b/tools/pharos-dashboard/src/pharos_dashboard/urls.py deleted file mode 100644 index adcb5b8f..00000000 --- a/tools/pharos-dashboard/src/pharos_dashboard/urls.py +++ /dev/null @@ -1,44 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -"""pharos_dashboard URL Configuration - -The `urlpatterns` list routes URLs to views. For more information please see: - https://docs.djangoproject.com/en/1.10/topics/http/urls/ -Examples: -Function views - 1. Add an import: from my_app import views - 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') -Class-based views - 1. Add an import: from other_app.views import Home - 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') -Including another URLconf - 1. Import the include() function: from django.conf.urls import url, include - 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) -""" -from django.conf import settings -from django.conf.urls import url, include -from django.conf.urls.static import static -from django.contrib import admin - - -urlpatterns = [ - url(r'^', include('dashboard.urls', namespace='dashboard')), - url(r'^booking/', include('booking.urls', namespace='booking')), - url(r'^accounts/', include('account.urls', namespace='account')), - - url(r'^admin/', admin.site.urls), - url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')), - - url(r'^api/', include('api.urls')) -] - -if settings.DEBUG is True: - urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
\ No newline at end of file diff --git a/tools/pharos-dashboard/src/pharos_dashboard/wsgi.py b/tools/pharos-dashboard/src/pharos_dashboard/wsgi.py deleted file mode 100644 index 3d43361b..00000000 --- a/tools/pharos-dashboard/src/pharos_dashboard/wsgi.py +++ /dev/null @@ -1,26 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Max Breitenfeldt and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -""" -WSGI config for pharos_dashboard project. - -It exposes the WSGI callable as a module-level variable named ``application``. - -For more information on this file, see -https://docs.djangoproject.com/en/1.10/howto/deployment/wsgi/ -""" - -import os - -from django.core.wsgi import get_wsgi_application - -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "pharos_dashboard.settings") - -application = get_wsgi_application() diff --git a/tools/pharos-dashboard/src/static/bower.json b/tools/pharos-dashboard/src/static/bower.json deleted file mode 100644 index f473747f..00000000 --- a/tools/pharos-dashboard/src/static/bower.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "pharos-dashboard-dependencies", - "authors": [ - "maxbr <maxbr@mi.fu-berlin.de>" - ], - "description": "This package contains all the Js/CSS dependencies needed to run the Pharos Dashboard.", - "main": "", - "license": "Apache2", - "homepage": "", - "private": true, - "ignore": [ - "**/.*", - "node_modules", - "bower_components", - "test", - "tests" - ], - "dependencies": { - "eonasdan-bootstrap-datetimepicker": "^4.17.37", - "fullcalendar": "^2.9.0", - "jquery-migrate": "^3.0.0", - "startbootstrap-sb-admin-2-blackrockdigital": "^3.3.7" - } -} diff --git a/tools/pharos-dashboard/src/static/css/theme.css b/tools/pharos-dashboard/src/static/css/theme.css deleted file mode 100644 index bd156372..00000000 --- a/tools/pharos-dashboard/src/static/css/theme.css +++ /dev/null @@ -1,13 +0,0 @@ -.blink_me { - animation: blinker 1.5s linear infinite; -} - -@keyframes blinker { - 20% { - opacity: 0.4; - } -} - -.modal p { - word-wrap: break-word; -}
\ No newline at end of file diff --git a/tools/pharos-dashboard/src/static/js/booking-calendar.js b/tools/pharos-dashboard/src/static/js/booking-calendar.js deleted file mode 100644 index f634293e..00000000 --- a/tools/pharos-dashboard/src/static/js/booking-calendar.js +++ /dev/null @@ -1,58 +0,0 @@ -/***************************************************************************** - * Copyright (c) 2016 Max Breitenfeldt and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Apache License, Version 2.0 - * which accompanies this distribution, and is available at - * http://www.apache.org/licenses/LICENSE-2.0 - *****************************************************************************/ - - -function parseCalendarEvents(bookings) { - var events = []; - for (var i = 0; i < bookings.length; i++) { - // convert ISO 8601 timestring to moment, needed for timezone handling - start = moment(bookings[i]['start']); - end = moment(bookings[i]['end']); - - installer = bookings[i]['installer__name']; - if (installer === null) { - installer = ''; - } - - scenario = bookings[i]['scenario__name']; - if (scenario === null) { - scenario = ''; - } - title = bookings[i]['purpose'] + ' ' + installer + ' ' + scenario; - - event = { - id: bookings[i]['id'], - title: title, - start: start, - end: end, - }; - events.push(event); - } - return events; -} - -function loadEvents(url) { - $.ajax({ - url: url, - type: 'get', - success: function (data) { - $('#calendar').fullCalendar('addEventSource', parseCalendarEvents(data['bookings'])); - }, - failure: function (data) { - alert('Error loading booking data'); - } - }); -} - -$(document).ready(function () { - $('#calendar').fullCalendar(calendarOptions); - loadEvents(bookings_url); - $('#starttimepicker').datetimepicker(timepickerOptions); - $('#endtimepicker').datetimepicker(timepickerOptions); -}); diff --git a/tools/pharos-dashboard/src/static/js/dataTables-sort.js b/tools/pharos-dashboard/src/static/js/dataTables-sort.js deleted file mode 100644 index 3072d2f1..00000000 --- a/tools/pharos-dashboard/src/static/js/dataTables-sort.js +++ /dev/null @@ -1,36 +0,0 @@ -/***************************************************************************** -* Copyright (c) 2016 Max Breitenfeldt and others. -* -* All rights reserved. This program and the accompanying materials -* are made available under the terms of the Apache License, Version 2.0 -* which accompanies this distribution, and is available at -* http://www.apache.org/licenses/LICENSE-2.0 -*****************************************************************************/ - - -/** - * This is a sort function for dataTables to sort tables by the status column. - * The order should be: online < online/idle < offline - */ -jQuery.extend(jQuery.fn.dataTableExt.oSort, { - "status-pre": function (a) { - switch (a) { - case 'online': - return 1; - case 'online / idle': - return 2; - case 'offline': - return 3; - default: - return a; - } - }, - - "status-asc": function (a, b) { - return ((a < b) ? -1 : ((a > b) ? 1 : 0)); - }, - - "status-desc": function (a, b) { - return ((a < b) ? 1 : ((a > b) ? -1 : 0)); - } -});
\ No newline at end of file diff --git a/tools/pharos-dashboard/src/static/js/datetimepicker-options.js b/tools/pharos-dashboard/src/static/js/datetimepicker-options.js deleted file mode 100644 index d43f5fb8..00000000 --- a/tools/pharos-dashboard/src/static/js/datetimepicker-options.js +++ /dev/null @@ -1,13 +0,0 @@ -/***************************************************************************** -* Copyright (c) 2016 Max Breitenfeldt and others. -* -* All rights reserved. This program and the accompanying materials -* are made available under the terms of the Apache License, Version 2.0 -* which accompanies this distribution, and is available at -* http://www.apache.org/licenses/LICENSE-2.0 -*****************************************************************************/ - - -var timepickerOptions = { - format: 'MM/DD/YYYY HH:00' -};
\ No newline at end of file diff --git a/tools/pharos-dashboard/src/static/js/flot-pie-chart.js b/tools/pharos-dashboard/src/static/js/flot-pie-chart.js deleted file mode 100644 index 3b80b2a2..00000000 --- a/tools/pharos-dashboard/src/static/js/flot-pie-chart.js +++ /dev/null @@ -1,30 +0,0 @@ -/***************************************************************************** -* Copyright (c) 2016 Max Breitenfeldt and others. -* -* All rights reserved. This program and the accompanying materials -* are made available under the terms of the Apache License, Version 2.0 -* which accompanies this distribution, and is available at -* http://www.apache.org/licenses/LICENSE-2.0 -*****************************************************************************/ - - -function loadChartData(chart_id, url) { - $.ajax({ - url: url, - type: 'get', - success: function (data) { - var data = data['data']; - var plotObj = $.plot($("#" + chart_id), data, { - series: { - pie: { - show: true - } - } - }); - }, - failure: function (data) { - alert('Error loading data'); - } - }); - -}
\ No newline at end of file diff --git a/tools/pharos-dashboard/src/static/js/fullcalendar-options.js b/tools/pharos-dashboard/src/static/js/fullcalendar-options.js deleted file mode 100644 index 22a1b95e..00000000 --- a/tools/pharos-dashboard/src/static/js/fullcalendar-options.js +++ /dev/null @@ -1,101 +0,0 @@ -/***************************************************************************** -* Copyright (c) 2016 Max Breitenfeldt and others. -* -* All rights reserved. This program and the accompanying materials -* are made available under the terms of the Apache License, Version 2.0 -* which accompanies this distribution, and is available at -* http://www.apache.org/licenses/LICENSE-2.0 -*****************************************************************************/ - - -var tmpevent; - -function sendEventToForm(event) { - $('#starttimepicker').data("DateTimePicker").date(event.start); - $('#endtimepicker').data("DateTimePicker").date(event.end); -} - -var calendarOptions = { - height: 600, - header: { - left: 'prev,next today', - center: 'title', - right: 'agendaWeek,month' - }, - timezone: user_timezone, // set in booking_calendar.html - defaultView: 'month', - slotDuration: '00:60:00', - slotLabelFormat: "HH:mm", - firstDay: 1, - allDaySlot: false, - selectOverlap: false, - eventOverlap: false, - selectable: true, - editable: false, - eventLimit: true, // allow "more" link when too many events - timeFormat: 'H(:mm)', // uppercase H for 24-hour clock - unselectAuto: true, - nowIndicator: true, - - // selectHelper is only working in the agendaWeek view, this is a workaround: - // if an event is selected, the existing selection is removed and a temporary event is added - // to the calendar - select: function (start, end) { - if (tmpevent != undefined) { - $('#calendar').fullCalendar('removeEvents', tmpevent.id); - $('#calendar').fullCalendar('rerenderEvents'); - tmpevent = undefined; - } - // the times need to be converted here to make them show up in the agendaWeek view if they - // are created in the month view. If they are not converted, the tmpevent will only show - // up in the (deactivated) allDaySlot - start = moment(start); - end = moment(end); - - tmpevent = { - id: '537818f62bc63518ece15338fb86c8be', - title: 'New Booking', - start: start, - end: end, - editable: true - }; - - $('#calendar').fullCalendar('renderEvent', tmpevent, true); - sendEventToForm(tmpevent); - }, - - eventClick: function (event) { - if (tmpevent != undefined) { - if (event.id != tmpevent.id) { - $('#calendar').fullCalendar('removeEvents', tmpevent.id); - $('#calendar').fullCalendar('rerenderEvents'); - tmpevent = undefined; - } - } - - // tmpevent is deleted if a real event is clicked, load event details - if (tmpevent == undefined) { - var booking_detail_url = booking_detail_prefix + event.id; - - $.ajax({ - url: booking_detail_url, - type: 'get', - success: function (data) { - $('#booking_detail_content').html(data); - }, - failure: function (data) { - alert('Error loading booking details'); - } - }); - $('#booking_detail_modal').modal('show'); - } - }, - - eventDrop: function (event) { - sendEventToForm(event); - }, - - eventResize: function (event) { - sendEventToForm(event); - } -};
\ No newline at end of file diff --git a/tools/pharos-dashboard/src/templates/account/user_list.html b/tools/pharos-dashboard/src/templates/account/user_list.html deleted file mode 100644 index 68178ebe..00000000 --- a/tools/pharos-dashboard/src/templates/account/user_list.html +++ /dev/null @@ -1,55 +0,0 @@ -{% extends "dashboard/table.html" %} -{% load staticfiles %} - -{% block table %} - <thead> - <tr> - <th>Username</th> - <th>Full Name</th> - <th>Email</th> - <th>Company</th> - <th>SSH Key</th> - <th>GPG Key</th> - </tr> - </thead> - <tbody> - {% for user in users %} - <tr> - <td> - {{ user.username }} - </td> - <td> - {{ user.userprofile.full_name }} - </td> - <td> - {{ user.email }} - </td> - <td> - {{ user.userprofile.company }} - </td> - <td> - {% if user.userprofile.ssh_public_key %} - <a href={{ user.userprofile.ssh_public_key.url }}>SSH</a> - {% endif %} - </td> - <td> - {% if user.userprofile.pgp_public_key %} - <a href={{ user.userprofile.pgp_public_key.url }}>GPG</a> - {% endif %} - </td> - </tr> - {% endfor %} - </tbody> -{% endblock table %} - - -{% block tablejs %} - <script type="text/javascript"> - $(document).ready(function () { - $('#table').DataTable({ - scrollX: true, - "order": [[0, "asc"]] - }); - }); - </script> -{% endblock tablejs %} diff --git a/tools/pharos-dashboard/src/templates/account/userprofile_update_form.html b/tools/pharos-dashboard/src/templates/account/userprofile_update_form.html deleted file mode 100644 index f4bb7b55..00000000 --- a/tools/pharos-dashboard/src/templates/account/userprofile_update_form.html +++ /dev/null @@ -1,38 +0,0 @@ -{% extends "layout.html" %} -{% load bootstrap3 %} - -{% block basecontent %} - <div class="container"> - <div class="row"> - <div class="col-md-4 col-md-offset-4"> - {% bootstrap_messages %} - <div class="login-panel panel panel-default"> - <div class="panel-heading"> - <h3 class="panel-title"> - {{ title }} - </h3> - </div> - <div class="panel-body"> - <form enctype="multipart/form-data" method="post"> - {% csrf_token %} - {% bootstrap_form form %} - <p><b>API Token</b> - <a href="{% url 'generate_token' %}" class="btn btn-default"> - Generate - </a> - </p> - <p style="word-wrap: break-word;">{{ token.key }}</p> - - <p></p> - {% buttons %} - <button type="submit" class="btn btn btn-success"> - Save Profile - </button> - {% endbuttons %} - </form> - </div> - </div> - </div> - </div> - </div> -{% endblock basecontent %} diff --git a/tools/pharos-dashboard/src/templates/base.html b/tools/pharos-dashboard/src/templates/base.html deleted file mode 100644 index 4d8530ad..00000000 --- a/tools/pharos-dashboard/src/templates/base.html +++ /dev/null @@ -1,111 +0,0 @@ -{% extends "layout.html" %} -{% load bootstrap3 %} - -{% block basecontent %} - <div id="wrapper"> - <!-- Navigation --> - <nav class="navbar navbar-default navbar-static-top" role="navigation" - style="margin-bottom: 0"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" - data-target=".navbar-collapse"> - <span class="sr-only">Toggle navigation</span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - <a href="https://www.opnfv.org/" class="navbar-left"><img - src="http://artifacts.opnfv.org/apex/review/14099/installation-instructions/_static/opnfv-logo.png"></a> - <a class="navbar-brand" href={% url 'dashboard:index' %}>Pharos Dashboard</a> - </div> - <!-- /.navbar-header --> - - <ul class="nav navbar-top-links navbar-right"> - <li class="dropdown"> - <a class="dropdown-toggle" data-toggle="dropdown" href="#"> - <i class="fa fa-user fa-fw"></i> <i class="fa fa-caret-down"></i> - </a> - <ul class="dropdown-menu dropdown-user"> - {% if user.is_authenticated %} - <li><a href="{% url 'account:settings' %}"><i - class="fa fa-gear fa-fw"></i> - Settings</a> - </li> - <li class="divider"></li> - <li><a href="{% url 'account:logout' %}?next={{ request.path }}"><i - class="fa fa-sign-out fa-fw"></i> - Logout</a> - </li> - {% else %} - <li><a href="{% url 'account:login' %}"><i - class="fa fa-sign-in fa-fw"></i> - Login with Jira</a> - <li> - {% endif %} - </ul> - <!-- /.dropdown-user --> - </li> - <!-- /.dropdown --> - </ul> - <!-- /.navbar-top-links --> - - <div class="navbar-default sidebar" role="navigation"> - <div class="sidebar-nav navbar-collapse"> - <ul class="nav" id="side-menu"> - <li> - <a href="{% url 'dashboard:ci_pods' %}"><i - class="fa fa-fw"></i>CI-Pods</a> - </li> - <li> - <a href="{% url 'dashboard:dev_pods' %}"><i - class="fa fa-fw"></i>Development - Pods</a> - </li> - <li> - <a href="{% url 'dashboard:jenkins_slaves' %}"><i - class="fa fa-fw"></i>Jenkins - Slaves</a> - </li> - <li> - {% if user.is_authenticated %} - <a href="{% url 'account:users' %}"><i - class="fa fa-fw"></i>User List - </a> - {% endif %} - </li> - <li> - <a href="{% url 'booking:list' %}"><i - class="fa fa-fw"></i>Booking List - </a> - </li> - <li> - <a href="{% url 'api-root' %}"><i - class="fa fa-fw"></i>API - </a> - </li> - </ul> - </div> - <!-- /.sidebar-collapse --> - </div> - <!-- /.navbar-static-side --> - </nav> - - <!-- Page Content --> - <div id="page-wrapper"> - <div class="row"> - <div class="col-lg-12"> - <h1 class="page-header">{{ title }}</h1> - </div> - <!-- /.col-lg-12 --> - </div> - - {% bootstrap_messages %} - - {% block content %} - - {% endblock content %} - </div> - <!-- /#page-wrapper --> - </div> - <!-- /#wrapper --> -{% endblock basecontent %} diff --git a/tools/pharos-dashboard/src/templates/booking/booking_calendar.html b/tools/pharos-dashboard/src/templates/booking/booking_calendar.html deleted file mode 100644 index 4644e855..00000000 --- a/tools/pharos-dashboard/src/templates/booking/booking_calendar.html +++ /dev/null @@ -1,103 +0,0 @@ -{% extends "base.html" %} -{% load staticfiles %} - -{% load bootstrap3 %} - -{% block extrahead %} - <link href="{% static "bower_components/fullcalendar/dist/fullcalendar.css" %}" - rel='stylesheet'/> - <link href="{% static "bower_components/eonasdan-bootstrap-datetimepicker/build/css/bootstrap-datetimepicker.min.css" %}" - rel='stylesheet'/> -{% endblock extrahead %} - -{% block content %} - <div class="col-lg-8"> - <div class="container-fluid"> - <div class="panel panel-default"> - <div class="panel-heading"> - <i class="fa fa-calendar fa-fw"></i>Calendar - </div> - <div class="panel-body"> - <div id='calendar'> - </div> - </div> - <!-- /.panel-body --> - </div> - <!-- /.panel --> - </div> - </div> - - <div class="col-lg-4"> - <div class="panel panel-default"> - <div class="panel-heading"> - <i class="fa fa-edit fa-fw"></i>Booking - </div> - <div class="panel-body"> - {% if user.is_authenticated %} - <div id="booking_form_div"> - {% bootstrap_form_errors form type='non_fields' %} - <form method="post" action="" class="form" id="bookingform"> - {% csrf_token %} - - <div class='input-group' id='starttimepicker'> - {% bootstrap_field form.start addon_after='<span class="glyphicon glyphicon-calendar"></span>' %} - </div> - <div class='input-group' id='endtimepicker'> - {% bootstrap_field form.end addon_after='<span class="glyphicon glyphicon-calendar"></span>' %} - </div> - {% bootstrap_field form.purpose %} - {% bootstrap_field form.installer %} - {% bootstrap_field form.scenario %} - {% buttons %} - <button type="submit" class="btn btn btn-success"> - Book - </button> - {% endbuttons %} - </form> - </div> - {% else %} - <p>Please - <a href="{% url 'account:login' %}"> - login with Jira</a> - to book this Pod</p> - {% endif %} - </div> - </div> - </div> - - <div id="booking_detail_modal" class="modal fade" role="dialog"> - <div class="modal-dialog"> - - <!-- Modal content--> - <div class="modal-content"> - <div class="modal-header"> - <button type="button" class="close" data-dismiss="modal">×</button> - <h4 class="modal-title">Booking Detail</h4> - </div> - <div class="modal-body" id="booking_detail_content"> - </div> - <div class="modal-footer"> - <button type="button" class="btn btn-default" data-dismiss="modal">Close - </button> - </div> - </div> - - </div> - </div> -{% endblock content %} - -{% block extrajs %} - <script type="text/javascript"> - var bookings_url = "{% url 'booking:bookings_json' resource_id=resource.id %}"; - var booking_detail_prefix = "{% url 'booking:detail_prefix' %}"; - var user_timezone = "{{ request.user.userprofile.timezone }}" - </script> - - <script src={% static "bower_components/moment/moment.js" %}></script> - <script src={% static "bower_components/fullcalendar/dist/fullcalendar.js" %}></script> - <script type="text/javascript" - src={% static "bower_components/eonasdan-bootstrap-datetimepicker/build/js/bootstrap-datetimepicker.min.js" %}></script> - <script src={% static "js/fullcalendar-options.js" %}></script> - <script src={% static "js/datetimepicker-options.js" %}></script> - <script src={% static "js/booking-calendar.js" %}></script> -{% endblock extrajs %}
\ No newline at end of file diff --git a/tools/pharos-dashboard/src/templates/booking/booking_detail.html b/tools/pharos-dashboard/src/templates/booking/booking_detail.html deleted file mode 100644 index 4b016b29..00000000 --- a/tools/pharos-dashboard/src/templates/booking/booking_detail.html +++ /dev/null @@ -1,26 +0,0 @@ -{% load jira_filters %} - -<p> - <b>Resource: </b> - <a href="{{ booking.resource.url }}"> - {{ booking.resource.name }} - </a> -</p> -<p> - <b>User: </b> {{ booking.user.username }} -</p> -<p> - <b>Start: </b> {{ booking.start }} -</p> -<p> - <b>End: </b> {{ booking.end }} -</p> -<p> - <b>Purpose: </b> {{ booking.purpose }} -</p> -<p> - <b>Installer: </b> {{ booking.installer }} -</p> -<p> - <b>Scenario: </b> {{ booking.scenario }} -</p>
\ No newline at end of file diff --git a/tools/pharos-dashboard/src/templates/booking/booking_list.html b/tools/pharos-dashboard/src/templates/booking/booking_list.html deleted file mode 100644 index ccdc46d7..00000000 --- a/tools/pharos-dashboard/src/templates/booking/booking_list.html +++ /dev/null @@ -1,48 +0,0 @@ -{% extends "base.html" %} -{% load staticfiles %} - -{% block extrahead %} - <!-- DataTables CSS --> - <link href="{% static "bower_components/datatables-plugins/integration/bootstrap/3/dataTables.bootstrap.css" %}" - rel="stylesheet"> - - <!-- DataTables Responsive CSS --> - <link href="{% static "bower_components/datatables-responsive/css/dataTables.responsive.css" %}" - rel="stylesheet"> -{% endblock extrahead %} - -{% block content %} - <div class="row"> - <div class="panel-body"> - <div class="dataTables_wrapper"> - <table class="table table-striped table-bordered table-hover" id="table" - cellspacing="0" - width="100%"> - {% include "booking/booking_table.html" %} - </table> - </div> - <!-- /.table-responsive --> - <!-- /.panel-body --> - <!-- /.panel --> - </div> - <!-- /.col-lg-12 --> - </div> -{% endblock content %} - -{% block extrajs %} - <!-- DataTables JavaScript --> - <link href="{% static "bower_components/datatables-plugins/integration/bootstrap/3/dataTables.bootstrap.css" %}" - rel="stylesheet"> - - - <script src={% static "bower_components/datatables/media/js/jquery.dataTables.min.js" %}></script> - <script src={% static "bower_components/datatables-plugins/integration/bootstrap/3/dataTables.bootstrap.min.js" %}></script> - - <script type="text/javascript"> - $(document).ready(function () { - $('#table').DataTable({ - scrollX: true, - }); - }); - </script> -{% endblock extrajs %} diff --git a/tools/pharos-dashboard/src/templates/booking/booking_table.html b/tools/pharos-dashboard/src/templates/booking/booking_table.html deleted file mode 100644 index 655b0131..00000000 --- a/tools/pharos-dashboard/src/templates/booking/booking_table.html +++ /dev/null @@ -1,37 +0,0 @@ -{% load jira_filters %} - - -<thead> -<tr> - <th>User</th> - <th>Purpose</th> - <th>Start</th> - <th>End</th> - <th>Installer</th> - <th>Scenario</th> -</tr> -</thead> -<tbody> -{% for booking in bookings %} - <tr> - <td> - {{ booking.user.username }} - </td> - <td> - {{ booking.purpose }} - </td> - <td> - {{ booking.start }} - </td> - <td> - {{ booking.end }} - </td> - <td> - {{ booking.installer }} - </td> - <td> - {{ booking.scenario }} - </td> - </tr> -{% endfor %} -</tbody>
\ No newline at end of file diff --git a/tools/pharos-dashboard/src/templates/dashboard/ci_pods.html b/tools/pharos-dashboard/src/templates/dashboard/ci_pods.html deleted file mode 100644 index a20be957..00000000 --- a/tools/pharos-dashboard/src/templates/dashboard/ci_pods.html +++ /dev/null @@ -1,61 +0,0 @@ -{% extends "dashboard/table.html" %} -{% load staticfiles %} -{% load jenkins_filters %} - -{% block table %} - <thead> - <tr> - <th>Name</th> - <th>Slave Name</th> - <th>Status</th> - <th>Installer</th> - <th>Scenario</th> - <th>Branch</th> - <th>Job</th> - </tr> - </thead> - <tbody> - {% for pod in ci_pods %} - <tr> - <td> - <a target='_blank' href={{ pod.url }}>{{ pod.name }}</a> - </td> - <td> - <a target='_blank' href={{ pod.slave.url }}>{{ pod.slave.name }}</a> - </td> - <td style="background-color:{{ pod.slave.status | jenkins_status_color }}"> - {{ pod.slave.status }} - </td> - <td {{ pod.slave.last_job_result | jenkins_job_blink }}> - {{ pod.slave.last_job_installer }} - </td> - <td {{ pod.slave.last_job_result | jenkins_job_blink }}> - {{ pod.slave.last_job_scenario }} - </td> - <td {{ pod.slave.last_job_result | jenkins_job_blink }}> - {{ pod.slave.last_job_branch }} - </td> - <td><a {{ pod.slave.last_job_result | jenkins_job_blink }} - style="color:{{ pod.slave.last_job_result | jenkins_job_color }}" - target='_blank' - href={{ pod.slave.last_job_url }}>{{ pod.slave.last_job_name }}</a> - </td> - </tr> - {% endfor %} - </tbody> -{% endblock table %} - - -{% block tablejs %} - <script type="text/javascript"> - $(document).ready(function () { - $('#table').DataTable({ - scrollX: true, - columnDefs: [ - {type: 'status', targets: 2} - ], - "order": [[2, "asc"]] - }); - }); - </script> -{% endblock tablejs %} diff --git a/tools/pharos-dashboard/src/templates/dashboard/dev_pods.html b/tools/pharos-dashboard/src/templates/dashboard/dev_pods.html deleted file mode 100644 index a6f3b2ee..00000000 --- a/tools/pharos-dashboard/src/templates/dashboard/dev_pods.html +++ /dev/null @@ -1,70 +0,0 @@ -{% extends "dashboard/table.html" %} -{% load staticfiles %} -{% load jenkins_filters %} - -{% block table %} - <thead> - <tr> - <th>Name</th> - <th>Slave Name</th> - <th>Booked by</th> - <th>Booked until</th> - <th>Purpose</th> - <th>Utilization</th> - <th>Status</th> - <th></th> - <th></th> - </tr> - </thead> - <tbody> - {% for pod, booking, utilization in dev_pods %} - <tr> - <td> - <a href={% url 'dashboard:resource' resource_id=pod.id %}>{{ pod.name }}</a> - </td> - <td> - <a target='_blank' href={{ pod.slave.url }}>{{ pod.slave.name }}</a> - </td> - <td> - {{ booking.user.username }} - </td> - <td> - {{ booking.end }} - </td> - <td> - {{ booking.purpose }} - </td> - <td> - {{ utilization }} - </td> - <td style="background-color:{{ pod.slave.status | jenkins_status_color }}"> - {{ pod.slave.status }} - </td> - <td> - <a href="{% url 'booking:create' resource_id=pod.id %}" class="btn btn-primary"> - Book - </a> - </td> - <td> - <a href="{% url 'dashboard:resource' resource_id=pod.id %}" class="btn btn-primary"> - Info - </a> - </td> - </tr> - {% endfor %} - </tbody> -{% endblock table %} - -{% block tablejs %} - <script type="text/javascript"> - $(document).ready(function () { - $('#table').DataTable({ - scrollX: true, - columnDefs: [ - {type: 'status', targets: 6} - ], - "order": [[6, "asc"]] - }); - }); - </script> -{% endblock tablejs %} diff --git a/tools/pharos-dashboard/src/templates/dashboard/jenkins_slaves.html b/tools/pharos-dashboard/src/templates/dashboard/jenkins_slaves.html deleted file mode 100644 index fa361b13..00000000 --- a/tools/pharos-dashboard/src/templates/dashboard/jenkins_slaves.html +++ /dev/null @@ -1,46 +0,0 @@ -{% extends "dashboard/table.html" %} -{% load staticfiles %} - -{% load jenkins_filters %} - -{% block table %} - <thead> - <tr> - <th>Slave name</th> - <th>Status</th> - <th>Job</th> - </tr> - </thead> - <tbody> - {% for slave in slaves %} - <tr> - <td><a target='_blank' - href={{ slave.url }}>{{ slave.name }}</a> - </td> - <td style="background-color:{{ slave.status | jenkins_status_color }}"> - {{ slave.status }} - </td> - <td><a {{ slave.last_job_result | jenkins_job_blink }} - style="color:{{ slave.last_job_result | jenkins_job_color }}" - target="_blank" href={{ slave.last_job_url }}> - {{ slave.last_job_name }}</a> - </td> - </tr> - {% endfor %} - </tbody> -{% endblock table %} - - -{% block tablejs %} - <script type="text/javascript"> - $(document).ready(function () { - $('#table').DataTable({ - scrollX: true, - columnDefs: [ - {type: 'status', targets: 1} - ], - "order": [[1, "asc"]] - }); - }); - </script> -{% endblock tablejs %} diff --git a/tools/pharos-dashboard/src/templates/dashboard/resource.html b/tools/pharos-dashboard/src/templates/dashboard/resource.html deleted file mode 100644 index c9e57354..00000000 --- a/tools/pharos-dashboard/src/templates/dashboard/resource.html +++ /dev/null @@ -1,58 +0,0 @@ -{% extends "base.html" %} -{% load staticfiles %} - -{% block extrahead %} - <!-- Morris Charts CSS --> - <link href="{% static "bower_components/morrisjs/morris.css" %}" rel="stylesheet"> - - <!-- DataTables CSS --> - <link href="{% static "bower_components/datatables-plugins/integration/bootstrap/3/dataTables.bootstrap.css" %}" - rel="stylesheet"> - - <!-- DataTables Responsive CSS --> - <link href="{% static "bower_components/datatables-responsive/css/dataTables.responsive.css" %}" - rel="stylesheet"> -{% endblock extrahead %} - - -{% block content %} - {% include "dashboard/resource_detail.html" %} -{% endblock content %} - - -{% block extrajs %} - <!-- DataTables JavaScript --> - <link href="{% static "bower_components/datatables-plugins/integration/bootstrap/3/dataTables.bootstrap.css" %}" - rel="stylesheet"> - - <script src={% static "bower_components/datatables/media/js/jquery.dataTables.min.js" %}></script> - <script src={% static "bower_components/datatables-plugins/integration/bootstrap/3/dataTables.bootstrap.min.js" %}></script> - - - - <!-- Flot Charts JavaScript --> - <script src="{% static "bower_components/flot/excanvas.min.js" %}"></script> - <script src="{% static "bower_components/flot/jquery.flot.js" %}"></script> - <script src="{% static "bower_components/flot/jquery.flot.pie.js" %}"></script> - <script src="{% static "bower_components/flot/jquery.flot.resize.js" %}"></script> - <script src="{% static "bower_components/flot/jquery.flot.time.js" %}"></script> - <script src="{% static "bower_components/flot.tooltip/js/jquery.flot.tooltip.min.js" %}"></script> - - <script src="{% static "js/flot-pie-chart.js" %}"></script> - - <script type="text/javascript"> - $(document).ready(function () { - $('#{{ resource.id }}_server_table').DataTable({}); - $('#{{ resource.id }}_bookings_table').DataTable({}); - $('#{{ resource.id }}_vpn_user_table').DataTable({}); - - var chart_id = "{{ resource.id }}_booking_utilization"; - var utilization_url = "{% url 'dashboard:booking_utilization' resource_id=resource.id weeks=4 %}"; - loadChartData(chart_id, utilization_url); - - var chart_id = "{{ resource.id }}_jenkins_utilization"; - var utilization_url = "{% url 'dashboard:jenkins_utilization' resource_id=resource.id weeks=1 %}"; - loadChartData(chart_id, utilization_url); - }); - </script> -{% endblock extrajs %}
\ No newline at end of file diff --git a/tools/pharos-dashboard/src/templates/dashboard/resource_all.html b/tools/pharos-dashboard/src/templates/dashboard/resource_all.html deleted file mode 100644 index a770d4e8..00000000 --- a/tools/pharos-dashboard/src/templates/dashboard/resource_all.html +++ /dev/null @@ -1,73 +0,0 @@ -{% extends "base.html" %} -{% load staticfiles %} - -{% block extrahead %} - <!-- Morris Charts CSS --> - <link href="{% static "bower_components/morrisjs/morris.css" %}" rel="stylesheet"> - - <!-- DataTables CSS --> - <link href="{% static "bower_components/datatables-plugins/integration/bootstrap/3/dataTables.bootstrap.css" %}" - rel="stylesheet"> - - <!-- DataTables Responsive CSS --> - <link href="{% static "bower_components/datatables-responsive/css/dataTables.responsive.css" %}" - rel="stylesheet"> -{% endblock extrahead %} - - -{% block content %} - {% for resource, utilization, bookings in pods %} - <div class="row"> - <div class="col-lg-12"> - <div class="panel panel-default"> - <div class="panel-heading"> - {{ resource.name }} - </div> - <div class="panel-body"> - {% include "dashboard/resource_detail.html" %} - </div> - </div> - </div> - </div> - {% endfor %} -{% endblock content %} - - -{% block extrajs %} - <!-- DataTables JavaScript --> - <link href="{% static "bower_components/datatables-plugins/integration/bootstrap/3/dataTables.bootstrap.css" %}" - rel="stylesheet"> - - <script src={% static "bower_components/datatables/media/js/jquery.dataTables.min.js" %}></script> - <script src={% static "bower_components/datatables-plugins/integration/bootstrap/3/dataTables.bootstrap.min.js" %}></script> - - - - <!-- Flot Charts JavaScript --> - <script src="{% static "bower_components/flot/excanvas.min.js" %}"></script> - <script src="{% static "bower_components/flot/jquery.flot.js" %}"></script> - <script src="{% static "bower_components/flot/jquery.flot.pie.js" %}"></script> - <script src="{% static "bower_components/flot/jquery.flot.resize.js" %}"></script> - <script src="{% static "bower_components/flot/jquery.flot.time.js" %}"></script> - <script src="{% static "bower_components/flot.tooltip/js/jquery.flot.tooltip.min.js" %}"></script> - <script src="{% static "js/flot-pie-chart.js" %}"></script>< - - <script type="text/javascript"> - $(document).ready(function () { - {% for resource, utilization, bookings in pods %} - - $('#{{ resource.id }}_server_table').DataTable({}); - $('#{{ resource.id }}_bookings_table').DataTable({}); - $('#{{ resource.id }}_vpn_user_table').DataTable({}); - - var chart_id = "{{ resource.id }}_booking_utilization"; - var utilization_url = "{% url 'dashboard:booking_utilization' resource_id=resource.id weeks=4 %}"; - loadChartData(chart_id, utilization_url); - - var chart_id = "{{ resource.id }}_jenkins_utilization"; - var utilization_url = "{% url 'dashboard:jenkins_utilization' resource_id=resource.id weeks=1 %}"; - loadChartData(chart_id, utilization_url); - {% endfor %} - }); - </script> -{% endblock extrajs %}
\ No newline at end of file diff --git a/tools/pharos-dashboard/src/templates/dashboard/resource_detail.html b/tools/pharos-dashboard/src/templates/dashboard/resource_detail.html deleted file mode 100644 index 740dd259..00000000 --- a/tools/pharos-dashboard/src/templates/dashboard/resource_detail.html +++ /dev/null @@ -1,205 +0,0 @@ -{% load jenkins_filters %} - -<div class="row"> - <div class="col-lg-3"> - <div class="panel panel-default"> - <div class="panel-heading"> - Jenkins Utilization - <div class="pull-right"> - <div class="form-group"> - <select onchange="loadChartData('{{ resource.id }}_jenkins_utilization', this.value);"> - <option value="{% url 'dashboard:jenkins_utilization' resource_id=resource.id weeks=1 %}"> - Last Week - </option> - <option value="{% url 'dashboard:jenkins_utilization' resource_id=resource.id weeks=4 %}"> - Last Month - </option> - </select> - </div> - </div> - </div> - <div class="panel-body"> - <div class="flot-chart"> - <div class="flot-chart-content" - id="{{ resource.id }}_jenkins_utilization"></div> - </div> - </div> - </div> - </div> - - <div class="col-lg-9"> - <div class="panel panel-default"> - <div class="panel-heading"> - Status - </div> - <div class="panel-body"> - <div class="list-group pre-scrollable"> - {% for status in resource.resourcestatus_set.all %} - <a href="#" class="list-group-item"> - <i class="fa fa-info fa-fw"></i> {{ status.title }} - <span class="pull-right text-muted small"> - <em>{{ status.timestamp }}</em> - </span> - </a> - {% endfor %} - </div> - </div> - </div> - </div> - <div class="col-lg-9"> - <div class="panel panel-default"> - <div class="panel-heading"> - Servers - </div> - <div class="panel-body"> - <div class="dataTables_wrapper"> - <table class="table table-striped table-bordered table-hover" - id="{{ resource.id }}_server_table" cellspacing="0" - width="100%"> - {% include "dashboard/server_table.html" %} - </table> - </div> - </div> - </div> - </div> -</div> -<div class="row"> - <div class="col-lg-3"> - <div class="panel panel-default"> - <div class="panel-heading"> - Booking Utilization - <div class="pull-right"> - <div class="form-group"> - <select onchange="loadChartData('{{ resource.id }}_booking_utilization', this.value);"> - <option value="{% url 'dashboard:booking_utilization' resource_id=resource.id weeks=-4 %}"> - Last Month - </option> - <option value="{% url 'dashboard:booking_utilization' resource_id=resource.id weeks=-1 %}"> - Last Week - </option> - <option value="{% url 'dashboard:booking_utilization' resource_id=resource.id weeks=1 %}"> - Next Week - </option> - <option selected="selected" - value="{% url 'dashboard:booking_utilization' resource_id=resource.id weeks=4 %}"> - Next Month - </option> - </select> - </div> - </div> - </div> - <div class="panel-body"> - <div class="flot-chart"> - <div class="flot-chart-content" - id="{{ resource.id }}_booking_utilization"></div> - </div> - </div> - </div> - </div> - <div class="col-lg-9"> - <div class="panel panel-default"> - <div class="panel-heading"> - Bookings - </div> - <div class="panel-body"> - <div class="dataTables_wrapper"> - <table class="table table-striped table-bordered table-hover" - id="{{ resource.id }}_bookings_table" cellspacing="0" - width="100%"> - {% include "booking/booking_table.html" %} - </table> - </div> - </div> - </div> - </div> -</div> -<div class="row"> - <div class="col-lg-3"> - <div class="panel panel-default"> - <div class="panel-heading"> - Contact - </div> - <div class="panel-body"> - <p> - <b>Lab Owner: </b> - {{ resource.owner.username }} - </p> - <p> - <b>Email: </b> - {{ resource.owner.email }} - </p> - <p> - <a href="{% url 'booking:create' resource_id=resource.id %}" class="btn - btn-primary"> - Booking - </a> - <a href="{{ resource.url }}" class="btn - btn-primary"> - OPNFV Wiki - </a> - </p> - </div> - </div> - </div> - <div class="col-lg-3"> - <div class="panel panel-default"> - <div class="panel-heading"> - Jenkins Status - </div> - <div class="panel-body"> - <p> - <b>Slave Name: </b> - <a target='_blank' - href={{ resource.slave.url }}>{{ resource.slave.name }}</a> - </p> - <p> - <b>Status: </b> - {{ resource.slave.status }} - </p> - <p> - <b>Last Job: </b> - <a href="{{ resource.slave.last_job_url }}"> - {{ resource.slave.last_job_name }} - </a> - </p> - </div> - </div> - </div> - <div class="col-lg-6"> - <div class="panel panel-default"> - <div class="panel-heading"> - VPN Users - </div> - <div class="panel-body"> - <div class="dataTables_wrapper"> - <table class="table table-striped table-bordered table-hover" - id="{{ resource.id }}_vpn_user_table" cellspacing="0" - width="100%"> - <thead> - <tr> - <th>User</th> - <th>Email</th> - <th>Company</th> - </tr> - </thead> - <tbody> - {% for user in resource.vpn_users.all %} - <tr> - <td> - {{ user.username }} - </td> - <td> - {{ user.email }} - </td> - <td> - {{ user.userprofile.company }} - </td> - </tr> - {% endfor %} - </table> - </tbody> - </div> - </div> - </div> - </div> -</div> diff --git a/tools/pharos-dashboard/src/templates/dashboard/server_table.html b/tools/pharos-dashboard/src/templates/dashboard/server_table.html deleted file mode 100644 index f01bd603..00000000 --- a/tools/pharos-dashboard/src/templates/dashboard/server_table.html +++ /dev/null @@ -1,30 +0,0 @@ -<thead> -<tr> - <th>Server</th> - <th>Model</th> - <th>CPU</th> - <th>RAM</th> - <th>Storage</th> -</tr> -</thead> -<tbody> -{% for server in resource.server_set.all %} - <tr> - <td> - {{ server.name }} - </td> - <td> - {{ server.model }} - </td> - <td> - {{ server.cpu }} - </td> - <td> - {{ server.ram }} - </td> - <td> - {{ server.storage }} - </td> - </tr> -{% endfor %} -</tbody>
\ No newline at end of file diff --git a/tools/pharos-dashboard/src/templates/dashboard/table.html b/tools/pharos-dashboard/src/templates/dashboard/table.html deleted file mode 100644 index d59f0e34..00000000 --- a/tools/pharos-dashboard/src/templates/dashboard/table.html +++ /dev/null @@ -1,43 +0,0 @@ -{% extends "base.html" %} -{% load staticfiles %} - -{% block extrahead %} - <!-- DataTables CSS --> - <link href="{% static "bower_components/datatables-plugins/integration/bootstrap/3/dataTables.bootstrap.css" %}" - rel="stylesheet"> - - <!-- DataTables Responsive CSS --> - <link href="{% static "bower_components/datatables-responsive/css/dataTables.responsive.css" %}" rel="stylesheet"> -{% endblock extrahead %} - -{% block content %} - <div class="row"> - <div class="col-lg-12"> - <div class="dataTables_wrapper"> - <table class="table table-striped table-bordered table-hover" id="table" cellspacing="0" - width="100%"> - - {% block table %} - {% endblock table %} - - </table> - </div> - <!-- /.table-responsive --> - <!-- /.panel-body --> - <!-- /.panel --> - </div> - <!-- /.col-lg-12 --> - </div> -{% endblock content %} - -{% block extrajs %} - <!-- DataTables JavaScript --> - - <script src={% static "bower_components/datatables/media/js/jquery.dataTables.min.js" %}></script> - <script src={% static "bower_components/datatables-plugins/integration/bootstrap/3/dataTables.bootstrap.min.js" %}></script> - - <script src={% static "js/dataTables-sort.js" %}></script> - - {% block tablejs %} - {% endblock tablejs %} -{% endblock extrajs %} diff --git a/tools/pharos-dashboard/src/templates/layout.html b/tools/pharos-dashboard/src/templates/layout.html deleted file mode 100644 index 9578e155..00000000 --- a/tools/pharos-dashboard/src/templates/layout.html +++ /dev/null @@ -1,73 +0,0 @@ -{% load staticfiles %} -<!DOCTYPE html> -<html lang="en"> - -<head> - - <meta charset="utf-8"> - <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1"> - <meta name="description" content=""> - <meta name="author" content=""> - - <title>OPNFV Pharos {{ title }}</title> - - <!-- Bootstrap Core CSS --> - <link href="{% static "bower_components/bootstrap/dist/css/bootstrap.min.css" %}" - rel="stylesheet"> - - <!-- MetisMenu CSS --> - <link href="{% static "bower_components/metisMenu/dist/metisMenu.min.css" %}" rel="stylesheet"> - - <!-- Custom CSS --> - <link href="{% static "bower_components/startbootstrap-sb-admin-2-blackrockdigital/dist/css/sb-admin-2.min.css" %}" - rel="stylesheet"> - <link href="{% static "css/theme.css" %}" rel="stylesheet"> - - <!-- Custom Fonts --> - <link href="{% static "bower_components/font-awesome/css/font-awesome.min.css" %}" - rel="stylesheet" type="text/css"> - - <!-- Favicon --> - <link rel="shortcut icon" href="{% static 'favicon.ico' %}"> - - {% block extrahead %} - {% endblock extrahead %} - - <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries --> - <!-- WARNING: Respond.js doesn't work if you view the page via file:// --> - <!--[if lt IE 9]> - <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script> - <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script> - <![endif]--> - -</head> - -{% block extrastyle %} -{% endblock extrastyle %} - -<body> -{% block basecontent %} -{% endblock basecontent %} - - -<script src="https://code.jquery.com/jquery-2.2.4.min.js" - integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script> -{#<!-- jQuery -->#} -{#<script src="{% static "bower_components/jquery/dist/jquery.min.js" %}"></script>#} -{#<script src="{% static "bower_components/jquery-migrate/jquery-migrate.min.js" %}"></script>#} - -{#<script src="https://code.jquery.com/jquery-2.2.0.min.js"></script>#} -<!-- Bootstrap Core JavaScript --> -<script src="{% static "bower_components/bootstrap/dist/js/bootstrap.min.js" %}"></script> - -<!-- Metis Menu Plugin JavaScript --> -<script src="{% static "bower_components/metisMenu/dist/metisMenu.min.js" %}"></script> - -<!-- Custom Theme JavaScript --> -<script src="{% static "bower_components/startbootstrap-sb-admin-2-blackrockdigital/dist/js/sb-admin-2.min.js" %}"></script> - -{% block extrajs %} -{% endblock extrajs %} -</body> -</html> diff --git a/tools/pharos-dashboard/src/templates/rest_framework/api.html b/tools/pharos-dashboard/src/templates/rest_framework/api.html deleted file mode 100644 index 9c6c4f7d..00000000 --- a/tools/pharos-dashboard/src/templates/rest_framework/api.html +++ /dev/null @@ -1,9 +0,0 @@ -{% extends "rest_framework/base.html" %} - -{% block title %}Pharos Dashboard API{% endblock %} - -{% block branding %} - <a class='navbar-brand' rel="nofollow" href=#> - Pharos Dashboard API - </a> -{% endblock %}
\ No newline at end of file diff --git a/tools/pharos-dashboard/web/Dockerfile b/tools/pharos-dashboard/web/Dockerfile deleted file mode 100644 index 228b0b0f..00000000 --- a/tools/pharos-dashboard/web/Dockerfile +++ /dev/null @@ -1,7 +0,0 @@ -FROM python:3.5 -ENV PYTHONUNBUFFERED 1 -RUN mkdir /config -ADD ./requirements.txt /config/ -RUN pip install -r /config/requirements.txt -RUN mkdir -p /pharos_dashboard/src -WORKDIR /pharos_dashboard/src diff --git a/tools/pharos-dashboard/web/requirements.txt b/tools/pharos-dashboard/web/requirements.txt deleted file mode 100644 index f80f1c07..00000000 --- a/tools/pharos-dashboard/web/requirements.txt +++ /dev/null @@ -1,17 +0,0 @@ -celery==3.1.23 -cryptography==1.4 -Django==1.10 -django-bootstrap3==7.0.1 -django-crispy-forms==1.6.0 -django-filter==0.14.0 -django-registration==2.1.2 -djangorestframework==3.4.6 -gunicorn==19.6.0 -jira==1.0.7 -jsonpickle==0.9.3 -oauth2==1.9.0.post1 -oauthlib==1.1.2 -pika==0.10.0 -psycopg2==2.6.2 -PyJWT==1.4.2 -requests==2.11.0 diff --git a/tools/pharos-dashboard/worker/Dockerfile b/tools/pharos-dashboard/worker/Dockerfile deleted file mode 100644 index c1e8aff7..00000000 --- a/tools/pharos-dashboard/worker/Dockerfile +++ /dev/null @@ -1,8 +0,0 @@ -FROM python:3.5 -ENV PYTHONUNBUFFERED 1 -RUN mkdir /config -ADD ./requirements.txt /config/ -RUN pip install -r /config/requirements.txt -RUN useradd -ms /bin/bash celery -USER celery -WORKDIR /pharos_dashboard/src diff --git a/tools/pharos-dashboard/worker/requirements.txt b/tools/pharos-dashboard/worker/requirements.txt deleted file mode 100644 index f80f1c07..00000000 --- a/tools/pharos-dashboard/worker/requirements.txt +++ /dev/null @@ -1,17 +0,0 @@ -celery==3.1.23 -cryptography==1.4 -Django==1.10 -django-bootstrap3==7.0.1 -django-crispy-forms==1.6.0 -django-filter==0.14.0 -django-registration==2.1.2 -djangorestframework==3.4.6 -gunicorn==19.6.0 -jira==1.0.7 -jsonpickle==0.9.3 -oauth2==1.9.0.post1 -oauthlib==1.1.2 -pika==0.10.0 -psycopg2==2.6.2 -PyJWT==1.4.2 -requests==2.11.0 |