From cd74ca6569b909ddfe70e575c54285cd4b049b0d Mon Sep 17 00:00:00 2001 From: Suman Chakravartula Date: Mon, 4 Dec 2017 06:04:47 -0800 Subject: [PATCH] return realtime info in task defition via properties. Fixes #1857 information like share_name and pool_name can be supplied when the model is serialized during a GET, by constructing it in real time. This pattern is already there in a few other models and works nicely for any information that shouldn't be stored in db or at least not duplicated. The other way of solving this problem is to have UI/client make explicit calls to appropriate end points to get share_name etc.. which is more RESTful, but introduces unnecessary complication in our case. --- src/rockstor/smart_manager/models/task_def.py | 25 +++ src/rockstor/smart_manager/serializers.py | 21 +- .../storageadmin/js/views/scheduled_tasks.js | 4 +- testing.cfg | 200 ++++++++++++++++++ 4 files changed, 239 insertions(+), 11 deletions(-) create mode 100644 testing.cfg diff --git a/src/rockstor/smart_manager/models/task_def.py b/src/rockstor/smart_manager/models/task_def.py index d967371d9..a59eeb713 100644 --- a/src/rockstor/smart_manager/models/task_def.py +++ b/src/rockstor/smart_manager/models/task_def.py @@ -16,7 +16,10 @@ along with this program. If not, see . """ +import json + from django.db import models +from storageadmin.models import (Pool, Share) class TaskDefinition(models.Model): @@ -39,3 +42,25 @@ class TaskDefinition(models.Model): class Meta: app_label = 'smart_manager' + + @property + def share_name(self, *args, **kwargs): + sn = None + if self.task_type == 'snapshot': + task_metadata = json.loads(self.json_meta) + try: + sn = Share.objects.get(id=task_metadata['share']).name + except Share.DoesNotExist: + sn = 'N/A' + return sn + + @property + def pool_name(self, *args, **kwargs): + pn = None + if self.task_type == 'scrub': + task_metadata = json.loads(self.json_meta) + try: + pn = Pool.objects.get(id=task_metadata['pool']).name + except Pool.DoesNotExist: + pn = 'N/A' + return pn diff --git a/src/rockstor/smart_manager/serializers.py b/src/rockstor/smart_manager/serializers.py index 6e8a5f371..610ed8737 100644 --- a/src/rockstor/smart_manager/serializers.py +++ b/src/rockstor/smart_manager/serializers.py @@ -17,15 +17,15 @@ """ from rest_framework import (serializers, pagination) -from smart_manager.models import (CPUMetric, LoadAvg, MemInfo, ServiceStatus, - SProbe, NFSDCallDistribution, - NFSDClientDistribution, - NFSDShareDistribution, - DiskStat, NetStat, - NFSDShareClientDistribution, - NFSDUidGidDistribution, TaskDefinition, Task, - Replica, ReplicaTrail, ReplicaShare, - ReceiveTrail, Service) +from .models import (CPUMetric, LoadAvg, MemInfo, ServiceStatus, + SProbe, NFSDCallDistribution, + NFSDClientDistribution, + NFSDShareDistribution, + DiskStat, NetStat, + NFSDShareClientDistribution, + NFSDUidGidDistribution, TaskDefinition, Task, + Replica, ReplicaTrail, ReplicaShare, + ReceiveTrail, Service) from smart_manager.taplib.probe_config import TapConfig @@ -118,6 +118,9 @@ def restore_object(self, attrs, instance=None): class TaskDefinitionSerializer(serializers.ModelSerializer): + share_name = serializers.CharField() + pool_name = serializers.CharField() + class Meta: model = TaskDefinition diff --git a/src/rockstor/storageadmin/static/storageadmin/js/views/scheduled_tasks.js b/src/rockstor/storageadmin/static/storageadmin/js/views/scheduled_tasks.js index b0590f1d2..658127ea6 100644 --- a/src/rockstor/storageadmin/static/storageadmin/js/views/scheduled_tasks.js +++ b/src/rockstor/storageadmin/static/storageadmin/js/views/scheduled_tasks.js @@ -145,11 +145,11 @@ ScheduledTasksView = RockstorLayoutView.extend({ if (taskType == 'snapshot') { // TODO: fix this to go direct to Snapshots tab. html += '('; - html += JSON.parse(jsonMeta).share_name + ')'; + html += t.get('share_name') + ')'; } else if (taskType == 'scrub') { // TODO: fix this to go direct to Scrubs tab. html += '('; - html += JSON.parse(jsonMeta).pool_name + ')'; + html += t.get('pool_name') + ')'; } html += ''; html += '' + prettyCron.toString(t.get('crontab')) + ''; diff --git a/testing.cfg b/testing.cfg new file mode 100644 index 000000000..0c5981967 --- /dev/null +++ b/testing.cfg @@ -0,0 +1,200 @@ +# Copyright (c) 2012-2013 RockStor, Inc. +# This file is part of RockStor. +# +# RockStor is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published +# by the Free Software Foundation; either version 2 of the License, +# or (at your option) any later version. +# +# RockStor is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +[buildout] +extends = base-buildout.cfg + +parts = + stop-rockstor + rpm-deps + rpm-deps-nut + django + scripts + postgres-setup + postgres-conf + gunicorn + nginx-conf + shellinabox-conf + stop-shellinabox + test-settings-conf + mime-types + init-gunicorn + extra-stuff + js-clean + js-libraries + js-sync + collectstatic + supervisor + supervisord-conf + create-cert + docker-conf + rockstor-pre-systemd-conf + rockstor-systemd-conf + bootstrap-systemd-conf + def-kernel + start-rockstor + + +[rpm-deps-ad] +recipe = plone.recipe.command +stop-on-error = true +command = + ${rpm-deps:install_cmd} realmd sssd oddjob oddjob-mkhomedir adcli \ + samba-common + +[nginx-conf] +recipe = collective.recipe.template +input = ${buildout:directory}/conf/nginx.conf.in +output = ${buildout:directory}/etc/nginx/nginx.conf + +[shellinabox-conf] +recipe = collective.recipe.template +input = ${buildout:directory}/conf/shellinaboxd.in +output = /etc/sysconfig/shellinaboxd + +[stop-shellinabox] +recipe = plone.recipe.command +command = systemctl stop shellinaboxd + +[stop-rockstor] +recipe = plone.recipe.command +command = systemctl stop rockstor +update-command = ${stop-rockstor:command} + +[start-rockstor] +recipe = plone.recipe.command +command = cp -f ${buildout:directory}/conf/rockstor-pre.service /etc/systemd/system/rockstor-pre.service && + systemctl enable rockstor-pre.service && + systemctl daemon-reload && + systemctl restart rockstor-pre + systemctl start rockstor +update-command = ${start-rockstor:command} + + +[init-gunicorn] +logfile = ${buildout:directory}/var/log/gunicorn.log +input = ${buildout:directory}/conf/gunicorn.in +output = ${buildout:directory}/etc/init.d/gunicorn + +[supervisord-conf] +logdir = ${buildout:directory}/var/log +gunicorn_cmd = ${buildout:directory}/bin/gunicorn --bind=${init-gunicorn:bind}:${init-gunicorn:port} --pid=${init-gunicorn:pidfile} --workers=${init-gunicorn:workers} --log-file=${init-gunicorn:logfile} --pythonpath=${buildout:directory}/src/rockstor --timeout=120 --graceful-timeout=120 wsgi:application +smart_manager_cmd = ${buildout:directory}/bin/sm +replicad_cmd = ${buildout:directory}/bin/replicad +dc_cmd = ${buildout:directory}/bin/data-collector +sm_cmd = ${buildout:directory}/bin/service-monitor +jd_cmd = ${buildout:directory}/bin/job-dispatcher +ztask_cmd = ${buildout:directory}/bin/django ztaskd --noreload -l DEBUG -f ${supervisord-conf:logdir}/ztask.log + +[django-settings-conf] +rootdir = ${buildout:directory}/src/rockstor +datastore = ${django-settings-conf:rootdir}/storageadmin/datastore +smartdb = ${django-settings-conf:rootdir}/smart_manager/smartdb +pgdata_dir = /var/lib/pgsql/data +static_dir = ${django-settings-conf:rootdir}/storageadmin/static/storageadmin +template_dir1 = ${django-settings-conf:rootdir}/storageadmin/templates/storageadmin +template_dir2 = ${django-settings-conf:rootdir}/templates/admin +logfile = ${buildout:directory}/var/log/rockstor.log +taplib = ${django-settings-conf:rootdir}/smart_manager/taplib +output = ${django-settings-conf:rootdir}/settings.py +debug = True +kernel = '4.12.4-1.el7.elrepo.x86_64' + +[test-settings-conf] +recipe = collective.recipe.template +input = ${buildout:directory}/conf/test-settings.conf.in +output = ${buildout:directory}/src/rockstor/test-settings.py + +# {storageadmin,smartdb}.sql.in are created using `pg_dump --username=rocky > .sql.in +[postgres-setup] +recipe = plone.recipe.command +command = if [[ ! -d ${django-settings-conf:pgdata_dir} ]]; then + echo "postgres not setup"; + systemctl enable postgresql; + postgresql-setup initdb; + systemctl restart postgresql; + su - postgres -c "createdb smartdb"; + su - postgres -c "createdb storageadmin"; + sudo -u postgres psql -c "CREATE ROLE rocky WITH SUPERUSER LOGIN PASSWORD 'rocky'"; + sudo -u postgres psql storageadmin < ${buildout:directory}/conf/storageadmin.sql.in; + sudo -u postgres psql smartdb < ${buildout:directory}/conf/smartdb.sql.in; + sudo -u postgres psql storageadmin -c "select setval('south_migrationhistory_id_seq', (select max(id) from south_migrationhistory))"; + sudo -u postgres psql smartdb -c "select setval('south_migrationhistory_id_seq', (select max(id) from south_migrationhistory))"; + fi +update-command = ${postgres-setup:command} + +[postgres-conf] +recipe = plone.recipe.command +command = su - postgres -c "cp -f ${buildout:directory}/conf/postgresql.conf /var/lib/pgsql/data/"; + su - postgres -c "cp -f ${buildout:directory}/conf/pg_hba.conf /var/lib/pgsql/data/"; + systemctl restart postgresql; +update-command = ${postgres-conf:command} + +[create-cert] +recipe = plone.recipe.command +cert_loc = ${buildout:directory}/certs +command = if [[ ! -d ${create-cert:cert_loc} ]]; then + mkdir ${create-cert:cert_loc}; + openssl req -nodes -newkey rsa:2048 -keyout ${create-cert:cert_loc}/first.key -out ${create-cert:cert_loc}/rockstor.csr -sha256 -subj "/C=US/ST=Rockstor user's state/L=Rockstor user's city/O=Rockstor user/OU=Rockstor dept/CN=rockstor.user" && + openssl rsa -in ${create-cert:cert_loc}/first.key -out ${create-cert:cert_loc}/rockstor.key && + openssl x509 -in ${create-cert:cert_loc}/rockstor.csr -out ${create-cert:cert_loc}/rockstor.cert -sha256 -req -signkey ${create-cert:cert_loc}/rockstor.key -days 3650 + fi +update-command = ${create-cert:command} + + +[def-kernel] +recipe = plone.recipe.command +command = grubby --set-default=/boot/vmlinuz-${django-settings-conf:kernel} +update-command = ${def-kernel:command} + +[fixtures] +recipe = plone.recipe.command +command = export DJANGO_SETTINGS_MODULE=settings && + ${buildout:directory}/bin/django dumpdata --exclude contenttypes --exclude auth.Permission --natural --indent 4 > ${buildout:directory}/src/rockstor/storageadmin/fixtures/newfixture.json +update-command = ${fixtures:command} + +[delete-prod-rpm] +recipe = plone.recipe.command +command = if [[ -d /opt/rockstor ]]; then + systemctl stop rockstor; + systemctl disable rockstor; + rm -rf /var/lib/pgsql/data; + sudo /usr/bin/yum remove -y rockstor; + rm -rf /opt/rockstor + fi +update-command = ${delete-prod-rpm:command} + +[js-libraries] +url = http://rockstor.com/downloads/jslibs-dev/lib.tgz +md5sum = 78f723aafcd05684f41193778fb0e26a + +[gulp-install] +recipe = plone.recipe.command +yum_install = sudo /usr/bin/yum install --setopt=timeout=600 -y +command = if [[ ! -f /usr/bin/gulp ]]; then + ${gulp-install:yum_install} npm; + npm install --global gulp-cli + fi +update-command = ${gulp-install:command} +stop-on-error = true + +[gulp-eslint] +recipe = plone.recipe.command +command = cd ${buildout:directory} && + npm install --save-dev --silent gulp && + npm install --save-dev --silent gulp-eslint && + gulp +update-command = ${gulp-eslint:command} +stop-on-error = true