mirror of
https://github.com/GNS3/gns3-server
synced 2024-12-25 16:28:11 +00:00
Merge pull request #1549 from GNS3/symbol-management-refactoring
Symbol management refactoring
This commit is contained in:
commit
21afaf31f9
@ -41,6 +41,14 @@ class Appliance:
|
|||||||
def status(self):
|
def status(self):
|
||||||
return self._data["status"]
|
return self._data["status"]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def symbol(self):
|
||||||
|
return self._data.get("symbol")
|
||||||
|
|
||||||
|
@symbol.setter
|
||||||
|
def symbol(self, new_symbol):
|
||||||
|
self._data["symbol"] = new_symbol
|
||||||
|
|
||||||
def __json__(self):
|
def __json__(self):
|
||||||
"""
|
"""
|
||||||
Appliance data (a hash)
|
Appliance data (a hash)
|
||||||
|
@ -74,7 +74,7 @@ class ApplianceManager:
|
|||||||
os.makedirs(appliances_path, exist_ok=True)
|
os.makedirs(appliances_path, exist_ok=True)
|
||||||
return appliances_path
|
return appliances_path
|
||||||
|
|
||||||
def load_appliances(self):
|
def load_appliances(self, symbol_theme="Classic"):
|
||||||
"""
|
"""
|
||||||
Loads appliance files from disk.
|
Loads appliance files from disk.
|
||||||
"""
|
"""
|
||||||
@ -90,13 +90,72 @@ class ApplianceManager:
|
|||||||
try:
|
try:
|
||||||
with open(path, 'r', encoding='utf-8') as f:
|
with open(path, 'r', encoding='utf-8') as f:
|
||||||
appliance = Appliance(appliance_id, json.load(f), builtin=builtin)
|
appliance = Appliance(appliance_id, json.load(f), builtin=builtin)
|
||||||
appliance.__json__() # Check if loaded without error
|
json_data = appliance.__json__() # Check if loaded without error
|
||||||
if appliance.status != 'broken':
|
if appliance.status != 'broken':
|
||||||
self._appliances[appliance.id] = appliance
|
self._appliances[appliance.id] = appliance
|
||||||
|
if not appliance.symbol or appliance.symbol.startswith(":/symbols/"):
|
||||||
|
# apply a default symbol if the appliance has none or a default symbol
|
||||||
|
default_symbol = self._get_default_symbol(json_data, symbol_theme)
|
||||||
|
if default_symbol:
|
||||||
|
appliance.symbol = default_symbol
|
||||||
except (ValueError, OSError, KeyError) as e:
|
except (ValueError, OSError, KeyError) as e:
|
||||||
log.warning("Cannot load appliance file '%s': %s", path, str(e))
|
log.warning("Cannot load appliance file '%s': %s", path, str(e))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
def _get_default_symbol(self, appliance, symbol_theme):
|
||||||
|
"""
|
||||||
|
Returns the default symbol for a given appliance.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from . import Controller
|
||||||
|
controller = Controller.instance()
|
||||||
|
category = appliance["category"]
|
||||||
|
if category == "guest":
|
||||||
|
if "docker" in appliance:
|
||||||
|
return controller.symbols.get_default_symbol("docker_guest", symbol_theme)
|
||||||
|
elif "qemu" in appliance:
|
||||||
|
return controller.symbols.get_default_symbol("qemu_guest", symbol_theme)
|
||||||
|
return controller.symbols.get_default_symbol(category, symbol_theme)
|
||||||
|
|
||||||
|
async def download_custom_symbols(self):
|
||||||
|
"""
|
||||||
|
Download custom appliance symbols from our GitHub registry repository.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from . import Controller
|
||||||
|
symbol_dir = Controller.instance().symbols.symbols_path()
|
||||||
|
self.load_appliances()
|
||||||
|
for appliance in self._appliances.values():
|
||||||
|
symbol = appliance.symbol
|
||||||
|
if symbol and not symbol.startswith(":/symbols/"):
|
||||||
|
destination_path = os.path.join(symbol_dir, symbol)
|
||||||
|
if not os.path.exists(destination_path):
|
||||||
|
await self._download_symbol(symbol, destination_path)
|
||||||
|
|
||||||
|
# refresh the symbol cache
|
||||||
|
Controller.instance().symbols.list()
|
||||||
|
|
||||||
|
async def _download_symbol(self, symbol, destination_path):
|
||||||
|
"""
|
||||||
|
Download a custom appliance symbol from our GitHub registry repository.
|
||||||
|
"""
|
||||||
|
|
||||||
|
symbol_url = "https://raw.githubusercontent.com/GNS3/gns3-registry/master/symbols/{}".format(symbol)
|
||||||
|
async with aiohttp.ClientSession() as session:
|
||||||
|
async with session.get(symbol_url) as response:
|
||||||
|
if response.status != 200:
|
||||||
|
log.warning("Could not retrieve appliance symbol {} from GitHub due to HTTP error code {}".format(symbol, response.status))
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
symbol_data = await response.read()
|
||||||
|
log.info("Saving {} symbol to {}".format(symbol, destination_path))
|
||||||
|
with open(destination_path, 'wb') as f:
|
||||||
|
f.write(symbol_data)
|
||||||
|
except asyncio.TimeoutError:
|
||||||
|
log.warning("Timeout while downloading '{}'".format(symbol_url))
|
||||||
|
except OSError as e:
|
||||||
|
log.warning("Could not write appliance symbol '{}': {}".format(destination_path, e))
|
||||||
|
|
||||||
@locking
|
@locking
|
||||||
async def download_appliances(self):
|
async def download_appliances(self):
|
||||||
"""
|
"""
|
||||||
@ -114,7 +173,7 @@ class ApplianceManager:
|
|||||||
log.info("Appliances are already up-to-date (ETag {})".format(self._appliances_etag))
|
log.info("Appliances are already up-to-date (ETag {})".format(self._appliances_etag))
|
||||||
return
|
return
|
||||||
elif response.status != 200:
|
elif response.status != 200:
|
||||||
raise aiohttp.web.HTTPConflict(text="Could not retrieve appliances on GitHub due to HTTP error code {}".format(response.status))
|
raise aiohttp.web.HTTPConflict(text="Could not retrieve appliances from GitHub due to HTTP error code {}".format(response.status))
|
||||||
etag = response.headers.get("ETag")
|
etag = response.headers.get("ETag")
|
||||||
if etag:
|
if etag:
|
||||||
self._appliances_etag = etag
|
self._appliances_etag = etag
|
||||||
@ -144,3 +203,6 @@ class ApplianceManager:
|
|||||||
raise aiohttp.web.HTTPConflict(text="Could not write appliance file '{}': {}".format(path, e))
|
raise aiohttp.web.HTTPConflict(text="Could not write appliance file '{}': {}".format(path, e))
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
raise aiohttp.web.HTTPConflict(text="Could not read appliances information from GitHub: {}".format(e))
|
raise aiohttp.web.HTTPConflict(text="Could not read appliances information from GitHub: {}".format(e))
|
||||||
|
|
||||||
|
# download the custom symbols
|
||||||
|
await self.download_custom_symbols()
|
||||||
|
@ -31,13 +31,13 @@ CLASSIC_SYMBOL_THEME = {"cloud": ":/symbols/classic/cloud.svg",
|
|||||||
"vmware_guest": ":/symbols/classic/vmware_guest.svg",
|
"vmware_guest": ":/symbols/classic/vmware_guest.svg",
|
||||||
"docker_guest": ":/symbols/classic/docker_guest.svg"}
|
"docker_guest": ":/symbols/classic/docker_guest.svg"}
|
||||||
|
|
||||||
INFINITY_SQUARE_BLUE_SYMBOL_THEME = {"cloud": ":/symbols/affinity/square/blue/cloud.svg",
|
AFFINITY_SQUARE_BLUE_SYMBOL_THEME = {"cloud": ":/symbols/affinity/square/blue/cloud.svg",
|
||||||
"ethernet_switch": ":/symbols/affinity/square/blue/switch.svg",
|
"ethernet_switch": ":/symbols/affinity/square/blue/switch.svg",
|
||||||
"ethernet_hub": ":/symbols/affinity/square/blue/hub.svg",
|
"ethernet_hub": ":/symbols/affinity/square/blue/hub.svg",
|
||||||
"frame_relay_switch.svg": ":/symbols/affinity/square/blue/isdn.svg",
|
"frame_relay_switch.svg": ":/symbols/affinity/square/blue/isdn.svg",
|
||||||
"atm_switch": ":/symbols/affinity/square/blue/atm.svg",
|
"atm_switch": ":/symbols/affinity/square/blue/atm.svg",
|
||||||
"router": ":/symbols/affinity/square/blue/router.svg",
|
"router": ":/symbols/affinity/square/blue/router.svg",
|
||||||
"multilayer_switch": ":/symbols/affinity/square/blue/multilayer_switch.svg",
|
"multilayer_switch": ":/symbols/affinity/square/blue/switch_multilayer.svg",
|
||||||
"firewall": ":/symbols/affinity/square/blue/firewall3.svg",
|
"firewall": ":/symbols/affinity/square/blue/firewall3.svg",
|
||||||
"computer": ":/symbols/affinity/square/blue/client.svg",
|
"computer": ":/symbols/affinity/square/blue/client.svg",
|
||||||
"vpcs_guest": ":/symbols/affinity/square/blue/client.svg",
|
"vpcs_guest": ":/symbols/affinity/square/blue/client.svg",
|
||||||
@ -46,13 +46,13 @@ INFINITY_SQUARE_BLUE_SYMBOL_THEME = {"cloud": ":/symbols/affinity/square/blue/cl
|
|||||||
"vmware_guest": ":/symbols/affinity/square/blue/vmware.svg",
|
"vmware_guest": ":/symbols/affinity/square/blue/vmware.svg",
|
||||||
"docker_guest": ":/symbols/affinity/square/blue/docker.svg"}
|
"docker_guest": ":/symbols/affinity/square/blue/docker.svg"}
|
||||||
|
|
||||||
INFINITY_SQUARE_RED_SYMBOL_THEME = {"cloud": ":/symbols/affinity/square/red/cloud.svg",
|
AFFINITY_SQUARE_RED_SYMBOL_THEME = {"cloud": ":/symbols/affinity/square/red/cloud.svg",
|
||||||
"ethernet_switch": ":/symbols/affinity/square/red/switch.svg",
|
"ethernet_switch": ":/symbols/affinity/square/red/switch.svg",
|
||||||
"ethernet_hub": ":/symbols/affinity/square/red/hub.svg",
|
"ethernet_hub": ":/symbols/affinity/square/red/hub.svg",
|
||||||
"frame_relay_switch": ":/symbols/affinity/square/red/isdn.svg",
|
"frame_relay_switch": ":/symbols/affinity/square/red/isdn.svg",
|
||||||
"atm_switch": ":/symbols/affinity/square/red/atm.svg",
|
"atm_switch": ":/symbols/affinity/square/red/atm.svg",
|
||||||
"router": ":/symbols/affinity/square/red/router.svg",
|
"router": ":/symbols/affinity/square/red/router.svg",
|
||||||
"multilayer_switch": ":/symbols/affinity/square/red/multilayer_switch.svg",
|
"multilayer_switch": ":/symbols/affinity/square/red/switch_multilayer.svg",
|
||||||
"firewall": ":/symbols/affinity/square/red/firewall3.svg",
|
"firewall": ":/symbols/affinity/square/red/firewall3.svg",
|
||||||
"computer": ":/symbols/affinity/square/red/client.svg",
|
"computer": ":/symbols/affinity/square/red/client.svg",
|
||||||
"vpcs_guest": ":/symbols/affinity/square/red/client.svg",
|
"vpcs_guest": ":/symbols/affinity/square/red/client.svg",
|
||||||
@ -61,13 +61,13 @@ INFINITY_SQUARE_RED_SYMBOL_THEME = {"cloud": ":/symbols/affinity/square/red/clou
|
|||||||
"vmware_guest": ":/symbols/affinity/square/red/vmware.svg",
|
"vmware_guest": ":/symbols/affinity/square/red/vmware.svg",
|
||||||
"docker_guest": ":/symbols/affinity/square/red/docker.svg"}
|
"docker_guest": ":/symbols/affinity/square/red/docker.svg"}
|
||||||
|
|
||||||
INFINITY_SQUARE_GRAY_SYMBOL_THEME = {"cloud": ":/symbols/affinity/square/gray/cloud.svg",
|
AFFINITY_SQUARE_GRAY_SYMBOL_THEME = {"cloud": ":/symbols/affinity/square/gray/cloud.svg",
|
||||||
"ethernet_switch": ":/symbols/affinity/square/gray/switch.svg",
|
"ethernet_switch": ":/symbols/affinity/square/gray/switch.svg",
|
||||||
"ethernet_hub": ":/symbols/affinity/square/gray/hub.svg",
|
"ethernet_hub": ":/symbols/affinity/square/gray/hub.svg",
|
||||||
"frame_relay_switch": ":/symbols/affinity/square/gray/isdn.svg",
|
"frame_relay_switch": ":/symbols/affinity/square/gray/isdn.svg",
|
||||||
"atm_switch": ":/symbols/affinity/square/gray/atm.svg",
|
"atm_switch": ":/symbols/affinity/square/gray/atm.svg",
|
||||||
"router": ":/symbols/affinity/square/gray/router.svg",
|
"router": ":/symbols/affinity/square/gray/router.svg",
|
||||||
"multilayer_switch": ":/symbols/affinity/square/gray/multilayer_switch.svg",
|
"multilayer_switch": ":/symbols/affinity/square/gray/switch_multilayer.svg",
|
||||||
"firewall": ":/symbols/affinity/square/gray/firewall3.svg",
|
"firewall": ":/symbols/affinity/square/gray/firewall3.svg",
|
||||||
"computer": ":/symbols/affinity/square/gray/client.svg",
|
"computer": ":/symbols/affinity/square/gray/client.svg",
|
||||||
"vpcs_guest": ":/symbols/affinity/square/gray/client.svg",
|
"vpcs_guest": ":/symbols/affinity/square/gray/client.svg",
|
||||||
@ -76,13 +76,13 @@ INFINITY_SQUARE_GRAY_SYMBOL_THEME = {"cloud": ":/symbols/affinity/square/gray/cl
|
|||||||
"vmware_guest": ":/symbols/affinity/square/gray/vmware.svg",
|
"vmware_guest": ":/symbols/affinity/square/gray/vmware.svg",
|
||||||
"docker_guest": ":/symbols/affinity/square/gray/docker.svg"}
|
"docker_guest": ":/symbols/affinity/square/gray/docker.svg"}
|
||||||
|
|
||||||
INFINITY_CIRCLE_BLUE_SYMBOL_THEME = {"cloud": ":/symbols/affinity/circle/blue/cloud.svg",
|
AFFINITY_CIRCLE_BLUE_SYMBOL_THEME = {"cloud": ":/symbols/affinity/circle/blue/cloud.svg",
|
||||||
"ethernet_switch": ":/symbols/affinity/circle/blue/switch.svg",
|
"ethernet_switch": ":/symbols/affinity/circle/blue/switch.svg",
|
||||||
"ethernet_hub": ":/symbols/affinity/circle/blue/hub.svg",
|
"ethernet_hub": ":/symbols/affinity/circle/blue/hub.svg",
|
||||||
"frame_relay_switch": ":/symbols/affinity/circle/blue/isdn.svg",
|
"frame_relay_switch": ":/symbols/affinity/circle/blue/isdn.svg",
|
||||||
"atm_switch": ":/symbols/affinity/circle/blue/atm.svg",
|
"atm_switch": ":/symbols/affinity/circle/blue/atm.svg",
|
||||||
"router": ":/symbols/affinity/circle/blue/router.svg",
|
"router": ":/symbols/affinity/circle/blue/router.svg",
|
||||||
"multilayer_switch": ":/symbols/affinity/circle/blue/multilayer_switch.svg",
|
"multilayer_switch": ":/symbols/affinity/circle/blue/switch_multilayer.svg",
|
||||||
"firewall": ":/symbols/affinity/circle/blue/firewall3.svg",
|
"firewall": ":/symbols/affinity/circle/blue/firewall3.svg",
|
||||||
"computer": ":/symbols/affinity/circle/blue/client.svg",
|
"computer": ":/symbols/affinity/circle/blue/client.svg",
|
||||||
"vpcs_guest": ":/symbols/affinity/circle/blue/client.svg",
|
"vpcs_guest": ":/symbols/affinity/circle/blue/client.svg",
|
||||||
@ -91,13 +91,13 @@ INFINITY_CIRCLE_BLUE_SYMBOL_THEME = {"cloud": ":/symbols/affinity/circle/blue/cl
|
|||||||
"vmware_guest": ":/symbols/affinity/circle/blue/vmware.svg",
|
"vmware_guest": ":/symbols/affinity/circle/blue/vmware.svg",
|
||||||
"docker_guest": ":/symbols/affinity/circle/blue/docker.svg"}
|
"docker_guest": ":/symbols/affinity/circle/blue/docker.svg"}
|
||||||
|
|
||||||
INFINITY_CIRCLE_RED_SYMBOL_THEME = {"cloud": ":/symbols/affinity/circle/red/cloud.svg",
|
AFFINITY_CIRCLE_RED_SYMBOL_THEME = {"cloud": ":/symbols/affinity/circle/red/cloud.svg",
|
||||||
"ethernet_switch": ":/symbols/affinity/circle/red/switch.svg",
|
"ethernet_switch": ":/symbols/affinity/circle/red/switch.svg",
|
||||||
"ethernet_hub": ":/symbols/affinity/circle/red/hub.svg",
|
"ethernet_hub": ":/symbols/affinity/circle/red/hub.svg",
|
||||||
"frame_relay_switch": ":/symbols/affinity/circle/red/isdn.svg",
|
"frame_relay_switch": ":/symbols/affinity/circle/red/isdn.svg",
|
||||||
"atm_switch": ":/symbols/affinity/circle/red/atm.svg",
|
"atm_switch": ":/symbols/affinity/circle/red/atm.svg",
|
||||||
"router": ":/symbols/affinity/circle/red/router.svg",
|
"router": ":/symbols/affinity/circle/red/router.svg",
|
||||||
"multilayer_switch": ":/symbols/affinity/circle/red/multilayer_switch.svg",
|
"multilayer_switch": ":/symbols/affinity/circle/red/switch_multilayer.svg",
|
||||||
"firewall": ":/symbols/affinity/circle/red/firewall3.svg",
|
"firewall": ":/symbols/affinity/circle/red/firewall3.svg",
|
||||||
"computer": ":/symbols/affinity/circle/red/client.svg",
|
"computer": ":/symbols/affinity/circle/red/client.svg",
|
||||||
"vpcs_guest": ":/symbols/affinity/circle/red/client.svg",
|
"vpcs_guest": ":/symbols/affinity/circle/red/client.svg",
|
||||||
@ -106,13 +106,13 @@ INFINITY_CIRCLE_RED_SYMBOL_THEME = {"cloud": ":/symbols/affinity/circle/red/clou
|
|||||||
"vmware_guest": ":/symbols/affinity/circle/red/vmware.svg",
|
"vmware_guest": ":/symbols/affinity/circle/red/vmware.svg",
|
||||||
"docker_guest": ":/symbols/affinity/circle/red/docker.svg"}
|
"docker_guest": ":/symbols/affinity/circle/red/docker.svg"}
|
||||||
|
|
||||||
INFINITY_CIRCLE_GRAY_SYMBOL_THEME = {"cloud": ":/symbols/affinity/circle/gray/cloud.svg",
|
AFFINITY_CIRCLE_GRAY_SYMBOL_THEME = {"cloud": ":/symbols/affinity/circle/gray/cloud.svg",
|
||||||
"ethernet_switch": ":/symbols/affinity/circle/gray/switch.svg",
|
"ethernet_switch": ":/symbols/affinity/circle/gray/switch.svg",
|
||||||
"ethernet_hub": ":/symbols/affinity/circle/gray/hub.svg",
|
"ethernet_hub": ":/symbols/affinity/circle/gray/hub.svg",
|
||||||
"frame_relay_switch": ":/symbols/affinity/circle/gray/isdn.svg",
|
"frame_relay_switch": ":/symbols/affinity/circle/gray/isdn.svg",
|
||||||
"atm_switch": ":/symbols/affinity/circle/gray/atm.svg",
|
"atm_switch": ":/symbols/affinity/circle/gray/atm.svg",
|
||||||
"router": ":/symbols/affinity/circle/gray/router.svg",
|
"router": ":/symbols/affinity/circle/gray/router.svg",
|
||||||
"multilayer_switch": ":/symbols/affinity/circle/gray/multilayer_switch.svg",
|
"multilayer_switch": ":/symbols/affinity/circle/gray/switch_multilayer.svg",
|
||||||
"firewall": ":/symbols/affinity/circle/gray/firewall3.svg",
|
"firewall": ":/symbols/affinity/circle/gray/firewall3.svg",
|
||||||
"computer": ":/symbols/affinity/circle/gray/client.svg",
|
"computer": ":/symbols/affinity/circle/gray/client.svg",
|
||||||
"vpcs_guest": ":/symbols/affinity/circle/gray/client.svg",
|
"vpcs_guest": ":/symbols/affinity/circle/gray/client.svg",
|
||||||
@ -122,9 +122,9 @@ INFINITY_CIRCLE_GRAY_SYMBOL_THEME = {"cloud": ":/symbols/affinity/circle/gray/cl
|
|||||||
"docker_guest": ":/symbols/affinity/circle/gray/docker.svg"}
|
"docker_guest": ":/symbols/affinity/circle/gray/docker.svg"}
|
||||||
|
|
||||||
BUILTIN_SYMBOL_THEMES = {"Classic": CLASSIC_SYMBOL_THEME,
|
BUILTIN_SYMBOL_THEMES = {"Classic": CLASSIC_SYMBOL_THEME,
|
||||||
"Infinity-square-blue": INFINITY_SQUARE_BLUE_SYMBOL_THEME,
|
"Affinity-square-blue": AFFINITY_SQUARE_BLUE_SYMBOL_THEME,
|
||||||
"Infinity-square-red": INFINITY_SQUARE_RED_SYMBOL_THEME,
|
"Affinity-square-red": AFFINITY_SQUARE_RED_SYMBOL_THEME,
|
||||||
"Infinity-square-gray": INFINITY_SQUARE_GRAY_SYMBOL_THEME,
|
"Affinity-square-gray": AFFINITY_SQUARE_GRAY_SYMBOL_THEME,
|
||||||
"Infinity-circle-blue": INFINITY_CIRCLE_BLUE_SYMBOL_THEME,
|
"Affinity-circle-blue": AFFINITY_CIRCLE_BLUE_SYMBOL_THEME,
|
||||||
"Infinity-circle-red": INFINITY_CIRCLE_RED_SYMBOL_THEME,
|
"Affinity-circle-red": AFFINITY_CIRCLE_RED_SYMBOL_THEME,
|
||||||
"Infinity-circle-gray": INFINITY_CIRCLE_GRAY_SYMBOL_THEME}
|
"Affinity-circle-gray": AFFINITY_CIRCLE_GRAY_SYMBOL_THEME}
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import aiohttp
|
||||||
import posixpath
|
import posixpath
|
||||||
|
|
||||||
from .symbol_themes import BUILTIN_SYMBOL_THEMES
|
from .symbol_themes import BUILTIN_SYMBOL_THEMES
|
||||||
@ -53,10 +54,24 @@ class Symbols:
|
|||||||
def theme(self, theme):
|
def theme(self, theme):
|
||||||
|
|
||||||
if not self._themes.get(theme):
|
if not self._themes.get(theme):
|
||||||
log.error("Could not find symbol theme '{}'".format(theme))
|
raise aiohttp.web.HTTPNotFound(text="Could not find symbol theme '{}'".format(theme))
|
||||||
return
|
|
||||||
self._current_theme = theme
|
self._current_theme = theme
|
||||||
|
|
||||||
|
def default_symbols(self):
|
||||||
|
|
||||||
|
return BUILTIN_SYMBOL_THEMES
|
||||||
|
|
||||||
|
def get_default_symbol(self, symbol, symbol_theme):
|
||||||
|
|
||||||
|
theme = self._themes.get(symbol_theme, None)
|
||||||
|
if not theme:
|
||||||
|
raise aiohttp.web.HTTPNotFound(text="Could not find symbol theme '{}'".format(symbol_theme))
|
||||||
|
symbol_path = theme.get(symbol)
|
||||||
|
if symbol_path not in self._symbols_path:
|
||||||
|
log.warning("Default symbol {} was not found".format(symbol_path))
|
||||||
|
return None
|
||||||
|
return symbol_path
|
||||||
|
|
||||||
def list(self):
|
def list(self):
|
||||||
|
|
||||||
self._symbols_path = {}
|
self._symbols_path = {}
|
||||||
@ -67,9 +82,11 @@ class Symbols:
|
|||||||
if filename.startswith('.'):
|
if filename.startswith('.'):
|
||||||
continue
|
continue
|
||||||
symbol_file = posixpath.normpath(os.path.relpath(os.path.join(root, filename), get_resource("symbols"))).replace('\\', '/')
|
symbol_file = posixpath.normpath(os.path.relpath(os.path.join(root, filename), get_resource("symbols"))).replace('\\', '/')
|
||||||
|
theme = posixpath.dirname(symbol_file).replace('/', '-').capitalize()
|
||||||
symbol_id = ':/symbols/' + symbol_file
|
symbol_id = ':/symbols/' + symbol_file
|
||||||
symbols.append({'symbol_id': symbol_id,
|
symbols.append({'symbol_id': symbol_id,
|
||||||
'filename': symbol_file,
|
'filename': filename,
|
||||||
|
'theme': theme,
|
||||||
'builtin': True})
|
'builtin': True})
|
||||||
self._symbols_path[symbol_id] = os.path.join(root, filename)
|
self._symbols_path[symbol_id] = os.path.join(root, filename)
|
||||||
|
|
||||||
@ -81,8 +98,9 @@ class Symbols:
|
|||||||
continue
|
continue
|
||||||
symbol_file = posixpath.normpath(os.path.relpath(os.path.join(root, filename), directory)).replace('\\', '/')
|
symbol_file = posixpath.normpath(os.path.relpath(os.path.join(root, filename), directory)).replace('\\', '/')
|
||||||
symbols.append({'symbol_id': symbol_file,
|
symbols.append({'symbol_id': symbol_file,
|
||||||
'filename': symbol_file,
|
'filename': filename,
|
||||||
'builtin': False,})
|
'builtin': False,
|
||||||
|
'theme': "Custom symbols"})
|
||||||
self._symbols_path[symbol_file] = os.path.join(root, filename)
|
self._symbols_path[symbol_file] = os.path.join(root, filename)
|
||||||
|
|
||||||
symbols.sort(key=lambda x: x["filename"])
|
symbols.sort(key=lambda x: x["filename"])
|
||||||
@ -99,21 +117,21 @@ class Symbols:
|
|||||||
return directory
|
return directory
|
||||||
|
|
||||||
def get_path(self, symbol_id):
|
def get_path(self, symbol_id):
|
||||||
symbol_filename = os.path.splitext(os.path.basename(symbol_id))[0]
|
|
||||||
theme = self._themes.get(self._current_theme, {})
|
|
||||||
if not theme:
|
|
||||||
log.error("Could not find symbol theme '{}'".format(self._current_theme))
|
|
||||||
try:
|
try:
|
||||||
return self._symbols_path[theme.get(symbol_filename, symbol_id)]
|
return self._symbols_path[symbol_id]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
# Symbol not found, let's refresh the cache
|
|
||||||
try:
|
try:
|
||||||
self.list()
|
self.list()
|
||||||
return self._symbols_path[symbol_id]
|
return self._symbols_path[symbol_id]
|
||||||
except (OSError, KeyError):
|
except (OSError, KeyError):
|
||||||
log.warning("Could not retrieve symbol '{}'".format(symbol_id))
|
# try to return a symbol with the same name from the classic theme
|
||||||
symbols_path = self._symbols_path
|
symbol = self._symbols_path.get(":/symbols/classic/{}".format(os.path.basename(symbol_id)))
|
||||||
return symbols_path.get(":/symbols/classic/{}".format(os.path.basename(symbol_id)), symbols_path[":/symbols/classic/computer.svg"])
|
if symbol:
|
||||||
|
return symbol
|
||||||
|
else:
|
||||||
|
# return the default computer symbol
|
||||||
|
log.warning("Could not retrieve symbol '{}'".format(symbol_id))
|
||||||
|
return self._symbols_path[":/symbols/classic/computer.svg"]
|
||||||
|
|
||||||
def get_size(self, symbol_id):
|
def get_size(self, symbol_id):
|
||||||
try:
|
try:
|
||||||
|
@ -38,5 +38,6 @@ class ApplianceHandler:
|
|||||||
controller = Controller.instance()
|
controller = Controller.instance()
|
||||||
if request.query.get("update", "no").lower() == "yes":
|
if request.query.get("update", "no").lower() == "yes":
|
||||||
await controller.appliance_manager.download_appliances()
|
await controller.appliance_manager.download_appliances()
|
||||||
controller.appliance_manager.load_appliances()
|
symbol_theme = request.query.get("symbol_theme", "Classic")
|
||||||
|
controller.appliance_manager.load_appliances(symbol_theme=symbol_theme)
|
||||||
response.json([c for c in controller.appliance_manager.appliances.values()])
|
response.json([c for c in controller.appliance_manager.appliances.values()])
|
||||||
|
@ -85,6 +85,17 @@ class SymbolHandler:
|
|||||||
controller.symbols.list()
|
controller.symbols.list()
|
||||||
response.set_status(204)
|
response.set_status(204)
|
||||||
|
|
||||||
|
@Route.get(
|
||||||
|
r"/default_symbols",
|
||||||
|
description="List of default symbols",
|
||||||
|
status_codes={
|
||||||
|
200: "Default symbols list returned"
|
||||||
|
})
|
||||||
|
def list_default_symbols(request, response):
|
||||||
|
|
||||||
|
controller = Controller.instance()
|
||||||
|
response.json(controller.symbols.default_symbols())
|
||||||
|
|
||||||
# @Route.post(
|
# @Route.post(
|
||||||
# r"/symbol_theme",
|
# r"/symbol_theme",
|
||||||
# description="Create a new symbol theme",
|
# description="Create a new symbol theme",
|
||||||
|
@ -51,6 +51,8 @@ class TemplateHandler:
|
|||||||
|
|
||||||
controller = Controller.instance()
|
controller = Controller.instance()
|
||||||
template = controller.template_manager.add_template(request.json)
|
template = controller.template_manager.add_template(request.json)
|
||||||
|
# Reset the symbol list
|
||||||
|
controller.symbols.list()
|
||||||
response.set_status(201)
|
response.set_status(201)
|
||||||
response.json(template)
|
response.json(template)
|
||||||
|
|
||||||
|
@ -259,16 +259,15 @@ def test_symbol(node, symbols_dir, controller):
|
|||||||
Change symbol should change the node size
|
Change symbol should change the node size
|
||||||
"""
|
"""
|
||||||
|
|
||||||
controller.symbols.theme = "Classic"
|
node.symbol = ":/symbols/classic/dslam.svg"
|
||||||
node.symbol = ":/symbols/dslam.svg"
|
assert node.symbol == ":/symbols/classic/dslam.svg"
|
||||||
assert node.symbol == ":/symbols/dslam.svg"
|
|
||||||
assert node.width == 50
|
assert node.width == 50
|
||||||
assert node.height == 53
|
assert node.height == 53
|
||||||
assert node.label["x"] is None
|
assert node.label["x"] is None
|
||||||
assert node.label["y"] == -40
|
assert node.label["y"] == -40
|
||||||
|
|
||||||
node.symbol = ":/symbols/cloud.svg"
|
node.symbol = ":/symbols/classic/cloud.svg"
|
||||||
assert node.symbol == ":/symbols/cloud.svg"
|
assert node.symbol == ":/symbols/classic/cloud.svg"
|
||||||
assert node.width == 159
|
assert node.width == 159
|
||||||
assert node.height == 71
|
assert node.height == 71
|
||||||
assert node.label["x"] is None
|
assert node.label["x"] is None
|
||||||
|
@ -31,13 +31,15 @@ def test_list(symbols_dir):
|
|||||||
symbols = Symbols()
|
symbols = Symbols()
|
||||||
assert {
|
assert {
|
||||||
'symbol_id': ':/symbols/classic/firewall.svg',
|
'symbol_id': ':/symbols/classic/firewall.svg',
|
||||||
'filename': 'classic/firewall.svg',
|
'filename': 'firewall.svg',
|
||||||
'builtin': True
|
'builtin': True,
|
||||||
|
'theme': 'Classic'
|
||||||
} in symbols.list()
|
} in symbols.list()
|
||||||
assert {
|
assert {
|
||||||
'symbol_id': 'linux.svg',
|
'symbol_id': 'linux.svg',
|
||||||
'filename': 'linux.svg',
|
'filename': 'linux.svg',
|
||||||
'builtin': False
|
'builtin': False,
|
||||||
|
'theme': 'Custom symbols'
|
||||||
} in symbols.list()
|
} in symbols.list()
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,8 +27,9 @@ def test_symbols(http_controller):
|
|||||||
assert response.status == 200
|
assert response.status == 200
|
||||||
assert {
|
assert {
|
||||||
'symbol_id': ':/symbols/classic/firewall.svg',
|
'symbol_id': ':/symbols/classic/firewall.svg',
|
||||||
'filename': 'classic/firewall.svg',
|
'filename': 'firewall.svg',
|
||||||
'builtin': True
|
'builtin': True,
|
||||||
|
'theme': 'Classic'
|
||||||
} in response.json
|
} in response.json
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user