mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-11-03 05:51:15 +02:00
1 parent
4f1b738ef5
commit
9dc6f0f486
11 files changed
+432
-27
No files matched your search
@@ -57,13 +57,12 @@ class Controller:
|
||||
|
||||
# Store settings shared by the different GUI will be replace by dedicated API later
|
||||
self._settings = None
|
||||
self._local_server = None
|
||||
self._appliances = {}
|
||||
self._appliance_templates = {}
|
||||
|
||||
self._config_file = os.path.join(Config.instance().config_dir, "gns3_controller.conf")
|
||||
log.info("Load controller configuration file {}".format(self._config_file))
|
||||
|
||||
self._appliance_templates = {}
|
||||
self.load_appliances()
|
||||
|
||||
def load_appliances(self):
|
||||
self._appliance_templates = {}
|
||||
for file in os.listdir(get_resource('appliances')):
|
||||
@@ -72,6 +71,59 @@ class Controller:
|
||||
if appliance.status != 'broken':
|
||||
self._appliance_templates[appliance.id] = appliance
|
||||
|
||||
self._appliances = {}
|
||||
for vm in self._settings.get("Qemu", {}).get("vms", []):
|
||||
vm["node_type"] = "qemu"
|
||||
appliance = Appliance(None, vm)
|
||||
self._appliances[appliance.id] = appliance
|
||||
for vm in self._settings.get("IOU", {}).get("devices", []):
|
||||
vm["node_type"] = "iou"
|
||||
appliance = Appliance(None, vm)
|
||||
self._appliances[appliance.id] = appliance
|
||||
for vm in self._settings.get("Docker", {}).get("containers", []):
|
||||
vm["node_type"] = "docker"
|
||||
appliance = Appliance(None, vm)
|
||||
self._appliances[appliance.id] = appliance
|
||||
for vm in self._settings.get("Builtin", {}).get("cloud_nodes", []):
|
||||
vm["node_type"] = "cloud"
|
||||
appliance = Appliance(None, vm)
|
||||
self._appliances[appliance.id] = appliance
|
||||
for vm in self._settings.get("Builtin", {}).get("ethernet_switches", []):
|
||||
vm["node_type"] = "ethernet_switch"
|
||||
appliance = Appliance(None, vm)
|
||||
self._appliances[appliance.id] = appliance
|
||||
for vm in self._settings.get("Builtin", {}).get("ethernet_hubs", []):
|
||||
vm["node_type"] = "ethernet_hub"
|
||||
appliance = Appliance(None, vm)
|
||||
self._appliances[appliance.id] = appliance
|
||||
for vm in self._settings.get("Dynamips", {}).get("routers", []):
|
||||
vm["node_type"] = "dynamips"
|
||||
appliance = Appliance(None, vm)
|
||||
self._appliances[appliance.id] = appliance
|
||||
for vm in self._settings.get("VMware", {}).get("vms", []):
|
||||
vm["node_type"] = "vmware"
|
||||
appliance = Appliance(None, vm)
|
||||
self._appliances[appliance.id] = appliance
|
||||
for vm in self._settings.get("VirtualBox", {}).get("vms", []):
|
||||
vm["node_type"] = "virtualbox"
|
||||
appliance = Appliance(None, vm)
|
||||
self._appliances[appliance.id] = appliance
|
||||
for vm in self._settings.get("VPCS", {}).get("nodes", []):
|
||||
vm["node_type"] = "vpcs"
|
||||
appliance = Appliance(None, vm)
|
||||
self._appliances[appliance.id] = appliance
|
||||
# Add builtins
|
||||
builtins = []
|
||||
builtins.append(Appliance(None, {"node_type": "cloud", "name": "Cloud", "category": 2, "symbol": ":/symbols/cloud.svg"}, builtin=True))
|
||||
builtins.append(Appliance(None, {"node_type": "nat", "name": "NAT", "category": 2, "symbol": ":/symbols/cloud.svg"}, builtin=True))
|
||||
builtins.append(Appliance(None, {"node_type": "vpcs", "name": "VPCS", "category": 2, "symbol": ":/symbols/vpcs_guest.svg"}, builtin=True))
|
||||
builtins.append(Appliance(None, {"node_type": "ethernet_switch", "name": "Ethernet switch", "category": 1, "symbol": ":/symbols/ethernet_switch.svg"}, builtin=True))
|
||||
builtins.append(Appliance(None, {"node_type": "ethernet_hub", "name": "Ethernet hub", "category": 1, "symbol": ":/symbols/hub.svg"}, builtin=True))
|
||||
builtins.append(Appliance(None, {"node_type": "frame_relay_switch", "name": "Frame Relay switch", "category": 1, "symbol": ":/symbols/frame_relay_switch.svg"}, builtin=True))
|
||||
builtins.append(Appliance(None, {"node_type": "atm_switch", "name": "ATM switch", "category": 1, "symbol": ":/symbols/atm_switch.svg"}, builtin=True))
|
||||
for b in builtins:
|
||||
self._appliances[b.id] = b
|
||||
|
||||
@asyncio.coroutine
|
||||
def start(self):
|
||||
log.info("Start controller")
|
||||
@@ -190,6 +242,7 @@ class Controller:
|
||||
if "gns3vm" in data:
|
||||
self.gns3vm.settings = data["gns3vm"]
|
||||
|
||||
self.load_appliances()
|
||||
return data["computes"]
|
||||
|
||||
@asyncio.coroutine
|
||||
@@ -309,6 +362,7 @@ class Controller:
|
||||
self._settings = val
|
||||
self._settings["modification_uuid"] = str(uuid.uuid4()) # We add a modification id to the settings it's help the gui to detect changes
|
||||
self.save()
|
||||
self.load_appliances()
|
||||
self.notification.emit("settings.updated", val)
|
||||
|
||||
@asyncio.coroutine
|
||||
@@ -515,6 +569,13 @@ class Controller:
|
||||
"""
|
||||
return self._appliance_templates
|
||||
|
||||
@property
|
||||
def appliances(self):
|
||||
"""
|
||||
:returns: The dictionary of appliances managed by GNS3
|
||||
"""
|
||||
return self._appliances
|
||||
|
||||
def projects_directory(self):
|
||||
server_config = Config.instance().get_section_config("Server")
|
||||
return os.path.expanduser(server_config.get("projects_path", "~/GNS3/projects"))
|
||||
|
||||
@@ -18,21 +18,56 @@
|
||||
import uuid
|
||||
|
||||
|
||||
# Convert old GUI category to text category
|
||||
ID_TO_CATEGORY = {
|
||||
3: "firewall",
|
||||
2: "guest",
|
||||
1: "switch",
|
||||
0: "router"
|
||||
}
|
||||
|
||||
|
||||
class Appliance:
|
||||
|
||||
def __init__(self, appliance_id, data):
|
||||
def __init__(self, appliance_id, data, builtin=False):
|
||||
if appliance_id is None:
|
||||
self._id = str(uuid.uuid4())
|
||||
else:
|
||||
self._id = appliance_id
|
||||
self._data = data
|
||||
self._builtin = builtin
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
return self._id
|
||||
|
||||
@property
|
||||
def data(self):
|
||||
return self._data
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._data["name"]
|
||||
|
||||
@property
|
||||
def compute_id(self):
|
||||
return self._data.get("server")
|
||||
|
||||
@property
|
||||
def builtin(self):
|
||||
return self._builtin
|
||||
|
||||
def __json__(self):
|
||||
"""
|
||||
Appliance data (a hash)
|
||||
"""
|
||||
return self._data
|
||||
return {
|
||||
"appliance_id": self._id,
|
||||
"node_type": self._data["node_type"],
|
||||
"name": self._data["name"],
|
||||
"default_name_format": self._data.get("default_name_format", "{name}-{0}"),
|
||||
"category": ID_TO_CATEGORY[self._data["category"]],
|
||||
"symbol": self._data["symbol"],
|
||||
"compute_id": self.compute_id,
|
||||
"builtin": self._builtin
|
||||
}
|
||||
@@ -19,6 +19,7 @@ import re
|
||||
import os
|
||||
import json
|
||||
import uuid
|
||||
import copy
|
||||
import shutil
|
||||
import asyncio
|
||||
import aiohttp
|
||||
@@ -317,6 +318,29 @@ class Project:
|
||||
return self.update_allocated_node_name(new_name)
|
||||
return new_name
|
||||
|
||||
@open_required
|
||||
@asyncio.coroutine
|
||||
def add_node_from_appliance(self, appliance_id, x=0, y=0, compute_id=None):
|
||||
"""
|
||||
Create a node from an appliance
|
||||
"""
|
||||
try:
|
||||
template = copy.copy(self.controller.appliances[appliance_id].data)
|
||||
except KeyError:
|
||||
msg = "Appliance {} doesn't exist".format(appliance_id)
|
||||
log.error(msg)
|
||||
raise aiohttp.web.HTTPNotFound(text=msg)
|
||||
template["x"] = x
|
||||
template["y"] = y
|
||||
node_type = template.pop("node_type")
|
||||
compute = self.controller.get_compute(template.pop("server", compute_id))
|
||||
name = template.pop("name")
|
||||
default_name_format = template.pop("default_name_format", "{name}-{0}")
|
||||
name = default_name_format.replace("{name}", name)
|
||||
node_id = str(uuid.uuid4())
|
||||
node = yield from self.add_node(compute, name, node_id, node_type=node_type, **template)
|
||||
return node
|
||||
|
||||
@open_required
|
||||
@asyncio.coroutine
|
||||
def add_node(self, compute, name, node_id, dump=True, node_type=None, **kwargs):
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
|
||||
from gns3server.web.route import Route
|
||||
from gns3server.controller import Controller
|
||||
from gns3server.schemas.node import NODE_OBJECT_SCHEMA
|
||||
from gns3server.schemas.appliance import APPLIANCE_USAGE_SCHEMA
|
||||
|
||||
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
@@ -27,6 +30,17 @@ class ApplianceHandler:
|
||||
|
||||
@Route.get(
|
||||
r"/appliances/templates",
|
||||
description="List of appliance templates",
|
||||
status_codes={
|
||||
200: "Appliance template list returned"
|
||||
})
|
||||
def list_templates(request, response):
|
||||
|
||||
controller = Controller.instance()
|
||||
response.json([c for c in controller.appliance_templates.values()])
|
||||
|
||||
@Route.get(
|
||||
r"/appliances",
|
||||
description="List of appliance",
|
||||
status_codes={
|
||||
200: "Appliance list returned"
|
||||
@@ -34,4 +48,27 @@ class ApplianceHandler:
|
||||
def list(request, response):
|
||||
|
||||
controller = Controller.instance()
|
||||
response.json([c for c in controller.appliance_templates.values()])
|
||||
response.json([c for c in controller.appliances.values()])
|
||||
|
||||
@Route.post(
|
||||
r"/projects/{project_id}/appliances/{appliance_id}",
|
||||
description="Create a node from an appliance",
|
||||
parameters={
|
||||
"project_id": "Project UUID",
|
||||
"appliance_id": "Appliance template UUID"
|
||||
},
|
||||
status_codes={
|
||||
201: "Node created",
|
||||
404: "The project or template doesn't exist"
|
||||
},
|
||||
input=APPLIANCE_USAGE_SCHEMA,
|
||||
output=NODE_OBJECT_SCHEMA)
|
||||
def create_node_from_appliance(request, response):
|
||||
|
||||
controller = Controller.instance()
|
||||
project = controller.get_project(request.match_info["project_id"])
|
||||
yield from project.add_node_from_appliance(request.match_info["appliance_id"],
|
||||
x=request.json["x"],
|
||||
y=request.json["y"],
|
||||
compute_id=request.json.get("compute_id"))
|
||||
response.set_status(201)
|
||||
@@ -0,0 +1,39 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
APPLIANCE_USAGE_SCHEMA = {
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"description": "Request validation to use an Appliance instance",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"x": {
|
||||
"description": "X position",
|
||||
"type": "integer"
|
||||
},
|
||||
"y": {
|
||||
"description": "Y position",
|
||||
"type": "integer"
|
||||
},
|
||||
"compute_id": {
|
||||
"description": "If the appliance don't have a default compute use this compute",
|
||||
"type": ["null", "string"]
|
||||
}
|
||||
},
|
||||
"additionalProperties": False,
|
||||
"required": ["x", "y"]
|
||||
}
|
||||
Reference in new issue
Block a user