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)
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):
"""
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_export import nvram_export
from .ioucon import start_ioucon
from gns3server.utils.file_watcher import FileWatcher
import gns3server.utils.asyncio
import gns3server.utils.images
import logging
import sys
log = logging.getLogger(__name__)
@ -91,9 +91,17 @@ class IOUVM(BaseNode):
self._ram = 256 # Megabytes
self._l1_keepalives = False # used to overcome the always-up Ethernet interfaces (not supported by all IOSes).
self._nvram_watcher = None
def _config(self):
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
def close(self):
"""
@ -424,6 +432,12 @@ class IOUVM(BaseNode):
self.iourc_path,
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):
"""
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
if startup_config_content:
nvram_file = os.path.join(self.working_dir, "nvram_{:05d}".format(self.application_id))
nvram_file = self._nvram_file()
try:
if not os.path.exists(nvram_file):
open(nvram_file, "a").close()
@ -489,6 +503,8 @@ class IOUVM(BaseNode):
# check if there is enough RAM to run
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.
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.
"""
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_*")):
shutil.move(file_path, destination)
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.
"""
if self._nvram_watcher:
self._nvram_watcher.close()
self._nvram_watcher = None
if self.is_running():
# stop console support
if self._ioucon_thread:

View File

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

View File

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