1
0
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:
grossmj 2019-03-05 17:29:01 +07:00
commit b0df7ecabf
14 changed files with 69 additions and 13 deletions

View File

@ -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.

View File

@ -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

View File

@ -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)

View File

@ -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
} }

View File

@ -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))

View File

@ -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,

View File

@ -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,

View File

@ -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

View File

@ -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",

View File

@ -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"

View File

@ -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__:

View File

@ -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

View File

@ -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
} }

View File

@ -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,