From 98e3a2e088f181edb168854311f5b2a359a3bb5d Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 28 Aug 2014 22:01:23 -0600 Subject: [PATCH 1/3] Updated requirements.txt --- requirements.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index ae4f8b0a..5f53f5ff 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,4 @@ netifaces -tornado +tornado==3.2.2 pyzmq -netifaces-py3 jsonschema From 3845cab84b4c740d17b25b25d11b3f146da73e05 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 28 Aug 2014 22:09:38 -0600 Subject: [PATCH 2/3] Adding initial module --- gns3server/modules/deadman/__init__.py | 95 ++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 gns3server/modules/deadman/__init__.py diff --git a/gns3server/modules/deadman/__init__.py b/gns3server/modules/deadman/__init__.py new file mode 100644 index 00000000..59cf106c --- /dev/null +++ b/gns3server/modules/deadman/__init__.py @@ -0,0 +1,95 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2014 GNS3 Technologies Inc. +# +# This program 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 3 of the License, or +# (at your option) any later version. +# +# This program 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 . + +""" +IOU server module. +""" + +import os +import base64 +import tempfile + +from gns3server.modules import IModule +from gns3server.config import Config + + +import logging +log = logging.getLogger(__name__) + +class DeadMan(): + """ + DeadMan module. + + :param name: module name + :param args: arguments for the module + :param kwargs: named arguments for the module + """ + + def __init__(self, name, *args, **kwargs): + config = Config.instance() + + # a new process start when calling IModule + IModule.__init__(self, name, *args, **kwargs) + self._host = kwargs["host"] + self._projects_dir = kwargs["projects_dir"] + self._tempdir = kwargs["temp_dir"] + self._working_dir = self._projects_dir + + # check every 5 seconds + #self._deadman_callback = self.add_periodic_callback(self._check_deadman_is_alive, 5000) + self._deadman_callback.start() + + def stop(self, signum=None): + """ + Properly stops the module. + + :param signum: signal number (if called by the signal handler) + """ + + self._iou_callback.stop() + + # delete all IOU instances + for iou_id in self._iou_instances: + iou_instance = self._iou_instances[iou_id] + iou_instance.delete() + + self.delete_iourc_file() + + IModule.stop(self, signum) # this will stop the I/O loop + + + @IModule.route("iou.reset") + def reset(self, request=None): + """ + Resets the module (JSON-RPC notification). + + :param request: JSON request (not used) + """ + + # delete all IOU instances + for iou_id in self._iou_instances: + iou_instance = self._iou_instances[iou_id] + iou_instance.delete() + + # resets the instance IDs + IOUDevice.reset() + + self._iou_instances.clear() + self._allocated_udp_ports.clear() + self.delete_iourc_file() + + log.info("IOU module has been reset") \ No newline at end of file From e688d96c36441cbfa2c7eae9c84377131ed69593 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 28 Aug 2014 23:06:28 -0600 Subject: [PATCH 3/3] Add start, stop, restart and heartbeat handling to DeadMan module --- gns3server/modules/deadman/__init__.py | 104 +++++++++++++++++++------ 1 file changed, 79 insertions(+), 25 deletions(-) diff --git a/gns3server/modules/deadman/__init__.py b/gns3server/modules/deadman/__init__.py index 59cf106c..ab81e971 100644 --- a/gns3server/modules/deadman/__init__.py +++ b/gns3server/modules/deadman/__init__.py @@ -16,12 +16,12 @@ # along with this program. If not, see . """ -IOU server module. +DeadMan server module. """ import os -import base64 -import tempfile +import time +import subprocess from gns3server.modules import IModule from gns3server.config import Config @@ -48,10 +48,45 @@ class DeadMan(): self._projects_dir = kwargs["projects_dir"] self._tempdir = kwargs["temp_dir"] self._working_dir = self._projects_dir - - # check every 5 seconds - #self._deadman_callback = self.add_periodic_callback(self._check_deadman_is_alive, 5000) - self._deadman_callback.start() + self._heartbeat_file = "%s/heartbeat_file_for_gnsdms" % ( + self._tempdir) + + if 'heartbeat_file' in kwargs: + self._heartbeat_file = kwargs['heartbeat_file'] + + + self._deadman_process = None + self.start() + + def _start_deadman_process(self): + """ + Start a subprocess and return the object + """ + + cmd = [] + + cmd.append("gns3dms") + cmd.append("--file %s" % (self._heartbeat_file)) + cmd.append("--background") + log.debug("Deadman: Running %s"%(cmd)) + + process = subprocess.Popen(cmd, shell=False) + return process + + def _stop_deadman_process(self): + """ + Start a subprocess and return the object + """ + + cmd = [] + + cmd.append("gns3dms") + cmd.append("-k") + log.debug("Deadman: Running %s"%(cmd)) + + process = subprocess.Popen(cmd, shell=False) + return process + def stop(self, signum=None): """ @@ -60,19 +95,26 @@ class DeadMan(): :param signum: signal number (if called by the signal handler) """ - self._iou_callback.stop() + if self._deadman_process == None: + log.info("Deadman: Can't stop, is not currently running") - # delete all IOU instances - for iou_id in self._iou_instances: - iou_instance = self._iou_instances[iou_id] - iou_instance.delete() - - self.delete_iourc_file() + log.debug("Deadman: Stopping process") + self._deadman_process = self._stop_deadman_process() + self._deadman_process = None + #Jerry or Jeremy why do we do this? Won't this stop the I/O loop for + #for everyone? IModule.stop(self, signum) # this will stop the I/O loop + def start(self, request=None): + """ + Start the deadman process on the server + """ - @IModule.route("iou.reset") + self._deadman_process = self._start_deadman_process() + log.debug("Deadman: Process is starting") + + @IModule.route("deadman.reset") def reset(self, request=None): """ Resets the module (JSON-RPC notification). @@ -80,16 +122,28 @@ class DeadMan(): :param request: JSON request (not used) """ - # delete all IOU instances - for iou_id in self._iou_instances: - iou_instance = self._iou_instances[iou_id] - iou_instance.delete() + self.stop() + self.start() - # resets the instance IDs - IOUDevice.reset() + log.info("Deadman: Module has been reset") - self._iou_instances.clear() - self._allocated_udp_ports.clear() - self.delete_iourc_file() - log.info("IOU module has been reset") \ No newline at end of file + @IModule.route("deadman.heartbeat") + def heartbeat(self, request=None): + """ + Update a file on the server that the deadman switch will monitor + """ + + now = time.time() + + with open(self._heartbeat_file, 'w') as heartbeat_file: + heartbeat_file.write(now) + heartbeat_file.close() + + log.debug("Deadman: heartbeat_file updated: %s %s" % ( + self._heartbeat_file, + now, + )) + + + self.start() \ No newline at end of file