mirror of
https://github.com/GNS3/gns3-server
synced 2024-11-30 20:28:08 +00:00
Merge branch '2.2' into import-export-refactoring
This commit is contained in:
commit
b0df7ecabf
20
CHANGELOG
20
CHANGELOG
@ -140,6 +140,26 @@
|
|||||||
* Implement #1153 into 2.2 branch.
|
* Implement #1153 into 2.2 branch.
|
||||||
* Pin prompt-toolkit to latest version 1.0.15
|
* Pin prompt-toolkit to latest version 1.0.15
|
||||||
|
|
||||||
|
## 2.1.14 27/02/2019
|
||||||
|
|
||||||
|
* Fix issue when setting cpuid.corespersocket for the GNS3 VM. Fixes https://github.com/GNS3/gns3-gui/issues/2723
|
||||||
|
* Bump ACPI Shutdown Timeout to 120 seconds. Ref #1536
|
||||||
|
|
||||||
|
## 2.1.13 26/02/2019
|
||||||
|
|
||||||
|
* Force jsonschema dependency to 2.6.0
|
||||||
|
* Less aggressive connections to uBridge. Ref #1289
|
||||||
|
* Fix topology images (Pictures) disappearing from projects. Fixes #1514.
|
||||||
|
* Reset MAC addresses when duplicating a project. Fixes #1522
|
||||||
|
* Fix API call to create a node from an appliance doesn't return the new node data. Fixes #1527
|
||||||
|
* Detect invalid environment variable and send a warning when creating a Docker node. Ref #2683
|
||||||
|
* Do not export/import symlinks for projects. Fixes #2699
|
||||||
|
* Fix symlink not being created for duplicated IOU devices. Fixes https://github.com/GNS3/gns3-gui/issues/2699
|
||||||
|
* Configure coresPerSocket value in VMX file for the GNS3 VM. Fixes https://github.com/GNS3/gns3-gui/issues/2688
|
||||||
|
* Count logical CPUs to detect if the number of vCPUs is too high when configuring the GNS3 VM. Fixes #2688.
|
||||||
|
* Add explicit error when trying to pull a Docker image from Docker Hub without Internet access. Fixes #1506.
|
||||||
|
* Fixes double display output in GRUB in QEMU v3.1. Fixes #1516.
|
||||||
|
|
||||||
## 2.1.12 23/01/2019
|
## 2.1.12 23/01/2019
|
||||||
|
|
||||||
* Tune how to get the size of SVG images. Ref https://github.com/GNS3/gns3-gui/issues/2674.
|
* Tune how to get the size of SVG images. Ref https://github.com/GNS3/gns3-gui/issues/2674.
|
||||||
|
@ -100,10 +100,10 @@ class Qemu(BaseManager):
|
|||||||
paths.update(["/usr/bin", "/usr/local/bin", "/opt/local/bin"])
|
paths.update(["/usr/bin", "/usr/local/bin", "/opt/local/bin"])
|
||||||
try:
|
try:
|
||||||
exec_dir = os.path.dirname(os.path.abspath(sys.executable))
|
exec_dir = os.path.dirname(os.path.abspath(sys.executable))
|
||||||
paths.add(os.path.abspath(os.path.join(exec_dir, "../Resources/qemu/bin/")))
|
paths.add(os.path.abspath(os.path.join(exec_dir, "qemu/bin")))
|
||||||
# If the user run the server by hand from outside
|
# If the user run the server by hand from outside
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
paths.add("/Applications/GNS3.app/Contents/Resources/qemu/bin")
|
paths.add("/Applications/GNS3.app/Contents/MacOS/qemu/bin")
|
||||||
return paths
|
return paths
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -984,7 +984,7 @@ class QemuVM(BaseNode):
|
|||||||
log.info("QEMU process has stopped, return code: %d", returncode)
|
log.info("QEMU process has stopped, return code: %d", returncode)
|
||||||
await self.stop()
|
await self.stop()
|
||||||
# A return code of 1 seem fine on Windows
|
# A return code of 1 seem fine on Windows
|
||||||
if returncode != 0 and (returncode != 1 or not sys.platform.startswith("win")):
|
if returncode != 0 and (not sys.platform.startswith("win") or returncode != 1):
|
||||||
self.project.emit("log.error", {"message": "QEMU process has stopped, return code: {}\n{}".format(returncode, self.read_stdout())})
|
self.project.emit("log.error", {"message": "QEMU process has stopped, return code: {}\n{}".format(returncode, self.read_stdout())})
|
||||||
|
|
||||||
async def stop(self):
|
async def stop(self):
|
||||||
@ -1013,7 +1013,7 @@ class QemuVM(BaseNode):
|
|||||||
|
|
||||||
if self.on_close == "shutdown_signal":
|
if self.on_close == "shutdown_signal":
|
||||||
await self._control_vm("system_powerdown")
|
await self._control_vm("system_powerdown")
|
||||||
await gns3server.utils.asyncio.wait_for_process_termination(self._process, timeout=30)
|
await gns3server.utils.asyncio.wait_for_process_termination(self._process, timeout=120)
|
||||||
else:
|
else:
|
||||||
self._process.terminate()
|
self._process.terminate()
|
||||||
await gns3server.utils.asyncio.wait_for_process_termination(self._process, timeout=3)
|
await gns3server.utils.asyncio.wait_for_process_termination(self._process, timeout=3)
|
||||||
|
@ -37,7 +37,7 @@ class Drawing:
|
|||||||
text, images, rectangle... They are pure SVG elements.
|
text, images, rectangle... They are pure SVG elements.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, project, drawing_id=None, svg="<svg></svg>", x=0, y=0, z=2, rotation=0):
|
def __init__(self, project, drawing_id=None, svg="<svg></svg>", x=0, y=0, z=2, locked=False, rotation=0):
|
||||||
self._project = project
|
self._project = project
|
||||||
if drawing_id is None:
|
if drawing_id is None:
|
||||||
self._id = str(uuid.uuid4())
|
self._id = str(uuid.uuid4())
|
||||||
@ -49,6 +49,7 @@ class Drawing:
|
|||||||
self._y = y
|
self._y = y
|
||||||
self._z = z
|
self._z = z
|
||||||
self._rotation = rotation
|
self._rotation = rotation
|
||||||
|
self._locked = locked
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def id(self):
|
def id(self):
|
||||||
@ -157,6 +158,14 @@ class Drawing:
|
|||||||
def z(self, val):
|
def z(self, val):
|
||||||
self._z = val
|
self._z = val
|
||||||
|
|
||||||
|
@property
|
||||||
|
def locked(self):
|
||||||
|
return self._locked
|
||||||
|
|
||||||
|
@locked.setter
|
||||||
|
def locked(self, val):
|
||||||
|
self._locked = val
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def rotation(self):
|
def rotation(self):
|
||||||
return self._rotation
|
return self._rotation
|
||||||
@ -198,6 +207,7 @@ class Drawing:
|
|||||||
"x": self._x,
|
"x": self._x,
|
||||||
"y": self._y,
|
"y": self._y,
|
||||||
"z": self._z,
|
"z": self._z,
|
||||||
|
"locked": self._locked,
|
||||||
"rotation": self._rotation,
|
"rotation": self._rotation,
|
||||||
"svg": self._svg
|
"svg": self._svg
|
||||||
}
|
}
|
||||||
@ -207,6 +217,7 @@ class Drawing:
|
|||||||
"x": self._x,
|
"x": self._x,
|
||||||
"y": self._y,
|
"y": self._y,
|
||||||
"z": self._z,
|
"z": self._z,
|
||||||
|
"locked": self._locked,
|
||||||
"rotation": self._rotation,
|
"rotation": self._rotation,
|
||||||
"svg": self.svg
|
"svg": self.svg
|
||||||
}
|
}
|
||||||
|
@ -73,11 +73,12 @@ class VMwareGNS3VM(BaseGNS3VM):
|
|||||||
if vcpus > available_vcpus:
|
if vcpus > available_vcpus:
|
||||||
raise GNS3VMError("You have allocated too many vCPUs for the GNS3 VM! (max available is {} vCPUs)".format(available_vcpus))
|
raise GNS3VMError("You have allocated too many vCPUs for the GNS3 VM! (max available is {} vCPUs)".format(available_vcpus))
|
||||||
|
|
||||||
cores_per_sockets = int(available_vcpus / psutil.cpu_count(logical=False))
|
|
||||||
try:
|
try:
|
||||||
pairs = VMware.parse_vmware_file(self._vmx_path)
|
pairs = VMware.parse_vmware_file(self._vmx_path)
|
||||||
pairs["numvcpus"] = str(vcpus)
|
pairs["numvcpus"] = str(vcpus)
|
||||||
pairs["cpuid.coresPerSocket"] = str(cores_per_sockets)
|
cores_per_sockets = int(available_vcpus / psutil.cpu_count(logical=False))
|
||||||
|
if cores_per_sockets >= 1:
|
||||||
|
pairs["cpuid.corespersocket"] = str(cores_per_sockets)
|
||||||
pairs["memsize"] = str(ram)
|
pairs["memsize"] = str(ram)
|
||||||
VMware.write_vmx_file(self._vmx_path, pairs)
|
VMware.write_vmx_file(self._vmx_path, pairs)
|
||||||
log.info("GNS3 VM vCPU count set to {} and RAM amount set to {}".format(vcpus, ram))
|
log.info("GNS3 VM vCPU count set to {} and RAM amount set to {}".format(vcpus, ram))
|
||||||
|
@ -34,7 +34,7 @@ log = logging.getLogger(__name__)
|
|||||||
|
|
||||||
class Node:
|
class Node:
|
||||||
# This properties are used only on controller and are not forwarded to the compute
|
# This properties are used only on controller and are not forwarded to the compute
|
||||||
CONTROLLER_ONLY_PROPERTIES = ["x", "y", "z", "width", "height", "symbol", "label", "console_host",
|
CONTROLLER_ONLY_PROPERTIES = ["x", "y", "z", "locked", "width", "height", "symbol", "label", "console_host",
|
||||||
"port_name_format", "first_port_name", "port_segment_size", "ports",
|
"port_name_format", "first_port_name", "port_segment_size", "ports",
|
||||||
"category", "console_auto_start"]
|
"category", "console_auto_start"]
|
||||||
|
|
||||||
@ -74,6 +74,7 @@ class Node:
|
|||||||
self._x = 0
|
self._x = 0
|
||||||
self._y = 0
|
self._y = 0
|
||||||
self._z = 1 # default z value is 1
|
self._z = 1 # default z value is 1
|
||||||
|
self._locked = False
|
||||||
self._ports = None
|
self._ports = None
|
||||||
self._symbol = None
|
self._symbol = None
|
||||||
self._custom_adapters = []
|
self._custom_adapters = []
|
||||||
@ -236,6 +237,14 @@ class Node:
|
|||||||
def z(self, val):
|
def z(self, val):
|
||||||
self._z = val
|
self._z = val
|
||||||
|
|
||||||
|
@property
|
||||||
|
def locked(self):
|
||||||
|
return self._locked
|
||||||
|
|
||||||
|
@locked.setter
|
||||||
|
def locked(self, val):
|
||||||
|
self._locked = val
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def width(self):
|
def width(self):
|
||||||
return self._width
|
return self._width
|
||||||
@ -681,6 +690,7 @@ class Node:
|
|||||||
"x": self._x,
|
"x": self._x,
|
||||||
"y": self._y,
|
"y": self._y,
|
||||||
"z": self._z,
|
"z": self._z,
|
||||||
|
"locked": self._locked,
|
||||||
"width": self._width,
|
"width": self._width,
|
||||||
"height": self._height,
|
"height": self._height,
|
||||||
"symbol": self._symbol,
|
"symbol": self._symbol,
|
||||||
@ -708,6 +718,7 @@ class Node:
|
|||||||
"x": self._x,
|
"x": self._x,
|
||||||
"y": self._y,
|
"y": self._y,
|
||||||
"z": self._z,
|
"z": self._z,
|
||||||
|
"locked": self._locked,
|
||||||
"width": self._width,
|
"width": self._width,
|
||||||
"height": self._height,
|
"height": self._height,
|
||||||
"symbol": self._symbol,
|
"symbol": self._symbol,
|
||||||
|
@ -1075,6 +1075,7 @@ class Project:
|
|||||||
data['x'] = x
|
data['x'] = x
|
||||||
data['y'] = y
|
data['y'] = y
|
||||||
data['z'] = z
|
data['z'] = z
|
||||||
|
data['locked'] = False # duplicated node must not be locked
|
||||||
new_node_uuid = str(uuid.uuid4())
|
new_node_uuid = str(uuid.uuid4())
|
||||||
new_node = await self.add_node(
|
new_node = await self.add_node(
|
||||||
node.compute,
|
node.compute,
|
||||||
|
@ -160,7 +160,7 @@ def load_topology(path):
|
|||||||
topo = _convert_2_1_0(topo, path)
|
topo = _convert_2_1_0(topo, path)
|
||||||
|
|
||||||
# Version GNS3 2.2 dev (for project created with 2.2dev).
|
# Version GNS3 2.2 dev (for project created with 2.2dev).
|
||||||
# Appliance ID has been repleace by Template ID
|
# Appliance ID has been replaced by Template ID
|
||||||
if topo["revision"] == 9:
|
if topo["revision"] == 9:
|
||||||
for node in topo.get("topology", {}).get("nodes", []):
|
for node in topo.get("topology", {}).get("nodes", []):
|
||||||
if "appliance_id" in node:
|
if "appliance_id" in node:
|
||||||
@ -177,7 +177,7 @@ def load_topology(path):
|
|||||||
try:
|
try:
|
||||||
with open(path, "w+", encoding="utf-8") as f:
|
with open(path, "w+", encoding="utf-8") as f:
|
||||||
json.dump(topo, f, indent=4, sort_keys=True)
|
json.dump(topo, f, indent=4, sort_keys=True)
|
||||||
except (OSError) as e:
|
except OSError as e:
|
||||||
raise aiohttp.web.HTTPConflict(text="Can't write the topology {}: {}".format(path, str(e)))
|
raise aiohttp.web.HTTPConflict(text="Can't write the topology {}: {}".format(path, str(e)))
|
||||||
return topo
|
return topo
|
||||||
|
|
||||||
|
@ -47,6 +47,10 @@ DRAWING_OBJECT_SCHEMA = {
|
|||||||
"description": "Z property",
|
"description": "Z property",
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
|
"locked": {
|
||||||
|
"description": "Whether the element locked or not",
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
"rotation": {
|
"rotation": {
|
||||||
"description": "Rotation of the element",
|
"description": "Rotation of the element",
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
|
@ -193,6 +193,10 @@ NODE_OBJECT_SCHEMA = {
|
|||||||
"description": "Z position of the node",
|
"description": "Z position of the node",
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
|
"locked": {
|
||||||
|
"description": "Whether the element locked or not",
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
"port_name_format": {
|
"port_name_format": {
|
||||||
"description": "Formating for port name {0} will be replace by port number",
|
"description": "Formating for port name {0} will be replace by port number",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
@ -23,8 +23,8 @@
|
|||||||
# or negative for a release candidate or beta (after the base version
|
# or negative for a release candidate or beta (after the base version
|
||||||
# number has been incremented)
|
# number has been incremented)
|
||||||
|
|
||||||
__version__ = "2.2.0a1"
|
__version__ = "2.2.0dev6"
|
||||||
__version_info__ = (2, 2, 0, -99)
|
__version_info__ = (2, 2, 0, 99)
|
||||||
|
|
||||||
# If it's a git checkout try to add the commit
|
# If it's a git checkout try to add the commit
|
||||||
if "dev" in __version__:
|
if "dev" in __version__:
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
jsonschema>=2.4.0
|
jsonschema==2.6.0 # pyup: ignore
|
||||||
aiohttp==3.5.4
|
aiohttp==3.5.4
|
||||||
aiohttp-cors==0.7.0
|
aiohttp-cors==0.7.0
|
||||||
aiofiles==0.4.0
|
aiofiles==0.4.0
|
||||||
|
@ -56,6 +56,7 @@ def test_json(project):
|
|||||||
"x": i.x,
|
"x": i.x,
|
||||||
"y": i.y,
|
"y": i.y,
|
||||||
"z": i.z,
|
"z": i.z,
|
||||||
|
"locked": i.locked,
|
||||||
"svg": i.svg,
|
"svg": i.svg,
|
||||||
"rotation": i.rotation
|
"rotation": i.rotation
|
||||||
}
|
}
|
||||||
@ -65,6 +66,7 @@ def test_json(project):
|
|||||||
"y": i.y,
|
"y": i.y,
|
||||||
"z": i.z,
|
"z": i.z,
|
||||||
"rotation": i.rotation,
|
"rotation": i.rotation,
|
||||||
|
"locked": i.locked,
|
||||||
"svg": i.svg
|
"svg": i.svg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,6 +135,7 @@ def test_json(node, compute):
|
|||||||
"x": node.x,
|
"x": node.x,
|
||||||
"y": node.y,
|
"y": node.y,
|
||||||
"z": node.z,
|
"z": node.z,
|
||||||
|
"locked": node.locked,
|
||||||
"width": node.width,
|
"width": node.width,
|
||||||
"height": node.height,
|
"height": node.height,
|
||||||
"symbol": node.symbol,
|
"symbol": node.symbol,
|
||||||
@ -167,6 +168,7 @@ def test_json(node, compute):
|
|||||||
"x": node.x,
|
"x": node.x,
|
||||||
"y": node.y,
|
"y": node.y,
|
||||||
"z": node.z,
|
"z": node.z,
|
||||||
|
"locked": node.locked,
|
||||||
"width": node.width,
|
"width": node.width,
|
||||||
"height": node.height,
|
"height": node.height,
|
||||||
"symbol": node.symbol,
|
"symbol": node.symbol,
|
||||||
|
Loading…
Reference in New Issue
Block a user