From 8eefaa3f32fbf041f5cfdf54a1a3fce47dec3549 Mon Sep 17 00:00:00 2001 From: grossmj Date: Wed, 27 May 2020 12:14:47 +0930 Subject: [PATCH] Option to reset or not all MAC addresses when exporting or duplicating a project. --- gns3server/controller/project.py | 5 +++-- .../handlers/api/controller/project_handler.py | 16 ++++++++++++---- gns3server/schemas/project.py | 9 +++++++++ 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/gns3server/controller/project.py b/gns3server/controller/project.py index 3c192660..43f9ab0e 100644 --- a/gns3server/controller/project.py +++ b/gns3server/controller/project.py @@ -999,7 +999,7 @@ class Project: while self._loading: await asyncio.sleep(0.5) - async def duplicate(self, name=None, location=None): + async def duplicate(self, name=None, location=None, reset_mac_addresses=True): """ Duplicate a project @@ -1009,6 +1009,7 @@ class Project: :param name: Name of the new project. A new one will be generated in case of conflicts :param location: Parent directory of the new project + :param reset_mac_addresses: Reset MAC addresses for the new project """ # If the project was not open we open it temporary previous_status = self._status @@ -1022,7 +1023,7 @@ class Project: with tempfile.TemporaryDirectory() as tmpdir: # Do not compress the exported project when duplicating with aiozipstream.ZipFile(compression=zipfile.ZIP_STORED) as zstream: - await export_project(zstream, self, tmpdir, keep_compute_id=True, allow_all_nodes=True, reset_mac_addresses=True) + await export_project(zstream, self, tmpdir, keep_compute_id=True, allow_all_nodes=True, reset_mac_addresses=reset_mac_addresses) # export the project to a temporary location project_path = os.path.join(tmpdir, "project.gns3p") diff --git a/gns3server/handlers/api/controller/project_handler.py b/gns3server/handlers/api/controller/project_handler.py index 066e2781..bec9605b 100644 --- a/gns3server/handlers/api/controller/project_handler.py +++ b/gns3server/handlers/api/controller/project_handler.py @@ -35,7 +35,8 @@ from gns3server.schemas.project import ( PROJECT_OBJECT_SCHEMA, PROJECT_UPDATE_SCHEMA, PROJECT_LOAD_SCHEMA, - PROJECT_CREATE_SCHEMA + PROJECT_CREATE_SCHEMA, + PROJECT_DUPLICATE_SCHEMA ) import logging @@ -313,6 +314,11 @@ class ProjectHandler: include_images = True else: include_images = False + if request.query.get("reset_mac_addresses", "no").lower() == "yes": + reset_mac_addresses = True + else: + reset_mac_addresses = False + compression_query = request.query.get("compression", "zip").lower() if compression_query == "zip": compression = zipfile.ZIP_DEFLATED @@ -327,7 +333,7 @@ class ProjectHandler: begin = time.time() with tempfile.TemporaryDirectory() as tmp_dir: with aiozipstream.ZipFile(compression=compression) as zstream: - await export_project(zstream, project, tmp_dir, include_snapshots=include_snapshots, include_images=include_images) + await export_project(zstream, project, tmp_dir, include_snapshots=include_snapshots, include_images=include_images, reset_mac_addresses=reset_mac_addresses) # We need to do that now because export could failed and raise an HTTP error # that why response start need to be the later possible @@ -398,7 +404,7 @@ class ProjectHandler: parameters={ "project_id": "Project UUID", }, - input=PROJECT_CREATE_SCHEMA, + input=PROJECT_DUPLICATE_SCHEMA, output=PROJECT_OBJECT_SCHEMA, status_codes={ 201: "Project duplicate", @@ -419,7 +425,9 @@ class ProjectHandler: else: location = None - new_project = await project.duplicate(name=request.json.get("name"), location=location) + reset_mac_addresses = request.json.get("reset_mac_addresses", False) + + new_project = await project.duplicate(name=request.json.get("name"), location=location, reset_mac_addresses=reset_mac_addresses) response.json(new_project) response.set_status(201) diff --git a/gns3server/schemas/project.py b/gns3server/schemas/project.py index 1c4e50d1..b65b745b 100644 --- a/gns3server/schemas/project.py +++ b/gns3server/schemas/project.py @@ -15,6 +15,8 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +import copy + SUPPLIER_OBJECT_SCHEMA = { "type": ["object", "null"], "description": "Supplier of the project", @@ -120,6 +122,13 @@ PROJECT_CREATE_SCHEMA = { "required": ["name"] } +# Create a project duplicate schema based on create schema and add "reset_mac_addresses" properties +PROJECT_DUPLICATE_SCHEMA = copy.deepcopy(PROJECT_CREATE_SCHEMA) +PROJECT_DUPLICATE_SCHEMA["description"] = "Request validation to duplicate a Project instance" +PROJECT_DUPLICATE_SCHEMA["properties"].update({"reset_mac_addresses": {"type": "boolean", + "description": "Reset MAC addresses for this project" + }}) + PROJECT_UPDATE_SCHEMA = { "$schema": "http://json-schema.org/draft-04/schema#", "description": "Request validation to update a Project instance",