Manage base configuration on server

Fix #786
This commit is contained in:
Julien Duponchelle committed 2017-02-03 13:19:14 +01:00
1 parent afcd27f348
commit e892e5dfab
32 files changed
+652 -334

No files matched your search

+26 -2
View File
@@ -16,9 +16,9 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
import sys
import json
import socket
import shutil
import asyncio
import aiohttp
@@ -30,7 +30,7 @@ from .symbols import Symbols
from ..version import __version__
from .topology import load_topology
from .gns3vm import GNS3VM
from ..utils.get_resource import get_resource
import logging
log = logging.getLogger(__name__)
@@ -54,6 +54,7 @@ class Controller:
@asyncio.coroutine
def start(self):
log.info("Start controller")
self.load_base_files()
yield from self.load()
server_config = Config.instance().get_section_config("Server")
host = server_config.get("host", "localhost")
@@ -163,6 +164,20 @@ class Controller:
except OSError as e:
log.error(str(e))
def load_base_files(self):
"""
At startup we copy base file to the user location to allow
them to customize it
"""
dst_path = self.configs_path()
src_path = get_resource('configs')
try:
for file in os.listdir(src_path):
if not os.path.exists(os.path.join(dst_path, file)):
shutil.copy(os.path.join(src_path, file), os.path.join(dst_path, file))
except OSError:
pass
def images_path(self):
"""
Get the image storage directory
@@ -172,6 +187,15 @@ class Controller:
os.makedirs(images_path, exist_ok=True)
return images_path
def configs_path(self):
"""
Get the configs storage directory
"""
server_config = Config.instance().get_section_config("Server")
images_path = os.path.expanduser(server_config.get("configs_path", "~/GNS3/projects"))
os.makedirs(images_path, exist_ok=True)
return images_path
@asyncio.coroutine
def _import_gns3_gui_conf(self):
"""
+28 -15
View File
@@ -146,6 +146,15 @@ class Node:
def properties(self, val):
self._properties = val
def _base_config_file_content(self, path):
if not os.path.isabs(path):
path = os.path.join(self.project.controller.configs_path(), path)
try:
with open(path) as f:
return f.read()
except (PermissionError, OSError):
return None
@property
def project(self):
return self._project
@@ -366,8 +375,12 @@ class Node:
self._console_type = value
elif key == "name":
self.name = value
elif key in ["node_id", "project_id", "console_host"]:
pass
elif key in ["node_id", "project_id", "console_host",
"startup_config_content",
"private_config_content",
"startup_script"]:
if key in self._properties:
del self._properties[key]
else:
self._properties[key] = value
self._list_ports()
@@ -384,6 +397,17 @@ class Node:
data = copy.copy(properties)
else:
data = copy.copy(self._properties)
# We replace the startup script name by the content of the file
mapping = {
"base_script_file": "startup_script",
"startup_config": "startup_config_content",
"private_config": "private_config_content",
}
for k, v in mapping.items():
if k in list(self._properties.keys()):
data[v] = self._base_config_file_content(self._properties[k])
del data[k]
del self._properties[k] # We send the file only one time
data["name"] = self._name
if self._console:
# console is optional for builtin nodes
@@ -585,17 +609,6 @@ class Node:
return False
return self.id == other.id and other.project.id == self.project.id
def _filter_properties(self):
"""
Some properties are private and should not be exposed
"""
PRIVATE_PROPERTIES = ("iourc_content", )
prop = copy.copy(self._properties)
for k in list(prop.keys()):
if k in PRIVATE_PROPERTIES:
del prop[k]
return prop
def __json__(self, topology_dump=False):
"""
:param topology_dump: Filter to keep only properties require for saving on disk
@@ -608,7 +621,7 @@ class Node:
"name": self._name,
"console": self._console,
"console_type": self._console_type,
"properties": self._filter_properties(),
"properties": self._properties,
"label": self._label,
"x": self._x,
"y": self._y,
@@ -631,7 +644,7 @@ class Node:
"console_host": str(self._compute.console_host),
"console_type": self._console_type,
"command_line": self._command_line,
"properties": self._filter_properties(),
"properties": self._properties,
"status": self._status,
"label": self._label,
"x": self._x,
+33 -1
View File
@@ -36,7 +36,7 @@ import logging
log = logging.getLogger(__name__)
GNS3_FILE_FORMAT_REVISION = 7
GNS3_FILE_FORMAT_REVISION = 8
def _check_topology_schema(topo):
@@ -138,6 +138,10 @@ def load_topology(path):
if topo["revision"] < 7:
topo = _convert_2_0_0_beta_2(topo, path)
# Version before GNS3 2.1
if topo["revision"] < 8:
topo = _convert_2_0_0(topo, path)
_check_topology_schema(topo)
if changed:
@@ -146,6 +150,34 @@ def load_topology(path):
return topo
def _convert_2_0_0(topo, topo_path):
"""
Convert topologies from GNS3 2.0.0 to 2.1
Changes:
* Remove startup_script_path from VPCS and base config file for IOU and Dynamips
"""
topo["revision"] = 8
for node in topo.get("topology", {}).get("nodes", []):
if "properties" in node:
if node["node_type"] == "vpcs":
if "startup_script_path" in node["properties"]:
del node["properties"]["startup_script_path"]
if "startup_script" in node["properties"]:
del node["properties"]["startup_script"]
elif node["node_type"] == "dynamips" or node["node_type"] == "iou":
if "startup_config" in node["properties"]:
del node["properties"]["startup_config"]
if "private_config" in node["properties"]:
del node["properties"]["private_config"]
if "startup_config_content" in node["properties"]:
del node["properties"]["startup_config_content"]
if "private_config_content" in node["properties"]:
del node["properties"]["private_config_content"]
return topo
def _convert_2_0_0_beta_2(topo, topo_path):
"""
Convert topologies from GNS3 2.0.0 beta 2 to beta 3.