Monitor IOU nvram for change

With the save as you go we need to save the startup config
when a change appear instead of the old commit system.
This commit is contained in:
Julien Duponchelle 2016-06-10 18:26:01 +02:00
parent 182a979e71
commit 69334665d2
No known key found for this signature in database
GPG Key ID: CE8B29639E07F5E8
4 changed files with 28 additions and 26 deletions

View File

@ -72,23 +72,6 @@ class IOU(BaseManager):
yield from super().close_node(node_id, *args, **kwargs) yield from super().close_node(node_id, *args, **kwargs)
return node return node
@asyncio.coroutine
def project_committed(self, project):
"""
Called when a project has been committed.
:param project: Project instance
"""
# save the configs when the project is committed
for node in self._nodes.copy().values():
if node.project.id == project.id:
try:
node.save_configs()
except IOUError as e:
log.warning(e)
continue
def get_application_id(self, node_id): def get_application_id(self, node_id):
""" """
Get an unique application identifier for IOU. Get an unique application identifier for IOU.

View File

@ -46,10 +46,10 @@ from ..base_node import BaseNode
from .utils.iou_import import nvram_import from .utils.iou_import import nvram_import
from .utils.iou_export import nvram_export from .utils.iou_export import nvram_export
from .ioucon import start_ioucon from .ioucon import start_ioucon
from gns3server.utils.file_watcher import FileWatcher
import gns3server.utils.asyncio import gns3server.utils.asyncio
import gns3server.utils.images import gns3server.utils.images
import logging import logging
import sys import sys
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -91,9 +91,17 @@ class IOUVM(BaseNode):
self._ram = 256 # Megabytes self._ram = 256 # Megabytes
self._l1_keepalives = False # used to overcome the always-up Ethernet interfaces (not supported by all IOSes). self._l1_keepalives = False # used to overcome the always-up Ethernet interfaces (not supported by all IOSes).
self._nvram_watcher = None
def _config(self): def _config(self):
return self._manager.config.get_section_config("IOU") return self._manager.config.get_section_config("IOU")
def _nvram_changed(self, path):
"""
Called when the NVRAM file as changed
"""
self.save_configs()
@asyncio.coroutine @asyncio.coroutine
def close(self): def close(self):
""" """
@ -424,6 +432,12 @@ class IOUVM(BaseNode):
self.iourc_path, self.iourc_path,
hostname)) hostname))
def _nvram_file(self):
"""
Path to the nvram file
"""
return os.path.join(self.working_dir, "nvram_{:05d}".format(self.application_id))
def _push_configs_to_nvram(self): def _push_configs_to_nvram(self):
""" """
Push the startup-config and private-config content to the NVRAM. Push the startup-config and private-config content to the NVRAM.
@ -431,7 +445,7 @@ class IOUVM(BaseNode):
startup_config_content = self.startup_config_content startup_config_content = self.startup_config_content
if startup_config_content: if startup_config_content:
nvram_file = os.path.join(self.working_dir, "nvram_{:05d}".format(self.application_id)) nvram_file = self._nvram_file()
try: try:
if not os.path.exists(nvram_file): if not os.path.exists(nvram_file):
open(nvram_file, "a").close() open(nvram_file, "a").close()
@ -489,6 +503,8 @@ class IOUVM(BaseNode):
# check if there is enough RAM to run # check if there is enough RAM to run
self.check_available_ram(self.ram) self.check_available_ram(self.ram)
self._nvram_watcher = FileWatcher(self._nvram_file(), self._nvram_changed)
# created a environment variable pointing to the iourc file. # created a environment variable pointing to the iourc file.
env = os.environ.copy() env = os.environ.copy()
@ -544,7 +560,7 @@ class IOUVM(BaseNode):
Before starting the VM, rename the nvram and vlan.dat files with the correct IOU application identifier. Before starting the VM, rename the nvram and vlan.dat files with the correct IOU application identifier.
""" """
destination = os.path.join(self.working_dir, "nvram_{:05d}".format(self.application_id)) destination = self._nvram_file()
for file_path in glob.glob(os.path.join(glob.escape(self.working_dir), "nvram_*")): for file_path in glob.glob(os.path.join(glob.escape(self.working_dir), "nvram_*")):
shutil.move(file_path, destination) shutil.move(file_path, destination)
destination = os.path.join(self.working_dir, "vlan.dat-{:05d}".format(self.application_id)) destination = os.path.join(self.working_dir, "vlan.dat-{:05d}".format(self.application_id))
@ -644,6 +660,10 @@ class IOUVM(BaseNode):
Stops the IOU process. Stops the IOU process.
""" """
if self._nvram_watcher:
self._nvram_watcher.close()
self._nvram_watcher = None
if self.is_running(): if self.is_running():
# stop console support # stop console support
if self._ioucon_thread: if self._ioucon_thread:

View File

@ -23,6 +23,7 @@ class FileWatcher:
""" """
Watch for file change and call the callback when something happen Watch for file change and call the callback when something happen
""" """
def __init__(self, path, callback, delay=1): def __init__(self, path, callback, delay=1):
if not isinstance(path, str): if not isinstance(path, str):
path = str(path) path = str(path)
@ -32,7 +33,7 @@ class FileWatcher:
self._closed = False self._closed = False
try: try:
self._mtime = os.stat(path).st_mtime self._mtime = os.stat(path).st_mtime_ns
except OSError: except OSError:
self._mtime = None self._mtime = None
asyncio.get_event_loop().call_later(self._delay, self._check_config_file_change) asyncio.get_event_loop().call_later(self._delay, self._check_config_file_change)
@ -48,9 +49,10 @@ class FileWatcher:
return return
changed = False changed = False
try: try:
if os.stat(self._path).st_mtime != self._mtime: mtime = os.stat(self._path).st_mtime_ns
if mtime != self._mtime:
changed = True changed = True
self._mtime = os.stat(self._path).st_mtime self._mtime = mtime
except OSError: except OSError:
self._mtime = None self._mtime = None
if changed: if changed:
@ -64,5 +66,3 @@ class FileWatcher:
@callback.setter @callback.setter
def callback(self, val): def callback(self, val):
self._callback = val self._callback = val

View File

@ -43,4 +43,3 @@ def test_file_watcher_not_existing(async_run, tmpdir):
file.write("b") file.write("b")
async_run(asyncio.sleep(1.5)) async_run(asyncio.sleep(1.5))
callback.assert_called_with(str(file)) callback.assert_called_with(str(file))