From f7c71b502f8757809d6b4d79818260c52c801455 Mon Sep 17 00:00:00 2001
From: Benjamin Bertrand <benjamin.bertrand@esss.se>
Date: Thu, 26 Apr 2018 10:16:45 +0200
Subject: [PATCH] Add function to update the TN core services

---
 app/network/views.py |  6 +++++-
 app/settings.py      |  3 +++
 app/tasks.py         | 44 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 52 insertions(+), 1 deletion(-)
 create mode 100644 app/tasks.py

diff --git a/app/network/views.py b/app/network/views.py
index 747d9f0..5fb7e3c 100644
--- a/app/network/views.py
+++ b/app/network/views.py
@@ -18,7 +18,7 @@ from .forms import (HostForm, InterfaceForm, HostInterfaceForm, NetworkForm,
                     NetworkScopeForm, DomainForm)
 from ..extensions import db
 from ..decorators import login_groups_accepted
-from .. import models, utils, helpers
+from .. import models, utils, helpers, tasks
 
 bp = Blueprint('network', __name__)
 
@@ -72,6 +72,7 @@ def create_host():
             flash(f'{e}', 'error')
         else:
             flash(f'Host {host} created!', 'success')
+            tasks.trigger_core_services_update()
         # Save network_id to the session to retrieve it after the redirect
         session['network_id'] = network_id
         return redirect(url_for('network.create_host'))
@@ -103,6 +104,7 @@ def edit_host(name):
             flash(f'{e}', 'error')
         else:
             flash(f'Host {host} updated!', 'success')
+            tasks.trigger_core_services_update()
         return redirect(url_for('network.view_host', name=host.name))
     return render_template('network/edit_host.html', form=form)
 
@@ -137,6 +139,7 @@ def create_interface(hostname):
             flash(f'{e}', 'error')
         else:
             flash(f'Host {interface} created!', 'success')
+            tasks.trigger_core_services_update()
         return redirect(url_for('network.create_interface', hostname=hostname))
     return render_template('network/create_interface.html', form=form, hostname=hostname)
 
@@ -199,6 +202,7 @@ def edit_interface(name):
             flash(f'{e}', 'error')
         else:
             flash(f'Interface {interface} updated!', 'success')
+            tasks.trigger_core_services_update()
         return redirect(url_for('network.view_host', name=interface.host.name))
     return render_template('network/edit_interface.html', form=form, hostname=interface.host.name)
 
diff --git a/app/settings.py b/app/settings.py
index e45241b..7fa4f6e 100644
--- a/app/settings.py
+++ b/app/settings.py
@@ -66,3 +66,6 @@ TEMPORARY_ICS_ID = 'ZZ'
 MAC_OUI = '02:42:42'
 
 DOCUMENTATION_URL = 'http://ics-infrastructure.pages.esss.lu.se/csentry/index.html'
+
+# AWX job templates
+AWX_CORE_SERVICES_UPDATE = 'ics-ans-core CSENTRY refresh'
diff --git a/app/tasks.py b/app/tasks.py
new file mode 100644
index 0000000..cc014f8
--- /dev/null
+++ b/app/tasks.py
@@ -0,0 +1,44 @@
+# -*- coding: utf-8 -*-
+"""
+app.tasks
+~~~~~~~~~
+
+This module implements tasks to run.
+
+:copyright: (c) 2018 European Spallation Source ERIC
+:license: BSD 2-Clause, see LICENSE for more details.
+
+"""
+import tower_cli
+from flask import current_app
+from rq import Queue
+
+
+def trigger_core_services_update():
+    """Trigger a job to update the core services on the TN (DNS and DHCP)
+
+    This function should be called every time an host or interface is created/edited
+
+    We can have one running job + one in queue to apply the latest changes.
+    Make sure that we don't have more than one in queue.
+    """
+    job_template = current_app.config['AWX_CORE_SERVICES_UPDATE']
+    q = Queue()
+    # Only trigger a new job if none is already waiting in queue
+    for job in q.jobs:
+        if (job.func_name == 'app.tasks.launch_job_template' and
+                job.kwargs.get('job_template', '') == job_template):
+            current_app.logger.info(f'Already one {job_template} job in queue. No need to trigger a new one.')
+            return None
+    current_app.logger.info(f'Launch new job to update core services: {job_template}')
+    job = q.enqueue(
+        launch_job_template,
+        job_template=job_template,
+    )
+    return job
+
+
+def launch_job_template(job_template, monitor=True, **kwargs):
+    resource = tower_cli.get_resource('job')
+    result = resource.launch(job_template=job_template, monitor=monitor, **kwargs)
+    return result
-- 
GitLab