Merge pull request #1459 from GNS3/duplicate-appliance

Support to duplicate an appliance via API. Fixes https://github.com/GNS3/gns3-gui/issues/2618
pull/1462/head
Jeremy Grossmann 6 years ago committed by GitHub
commit 3861d6a274
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -24,6 +24,7 @@ import shutil
import asyncio import asyncio
import aiohttp import aiohttp
import jsonschema import jsonschema
import copy
from ..config import Config from ..config import Config
from .project import Project from .project import Project
@ -181,6 +182,20 @@ class Controller:
self.save() self.save()
self.notification.controller_emit("appliance.deleted", appliance.__json__()) self.notification.controller_emit("appliance.deleted", appliance.__json__())
def duplicate_appliance(self, appliance_id):
"""
Duplicates an appliance.
:param appliance_id: appliance identifier
"""
appliance = self.get_appliance(appliance_id)
if appliance.builtin:
raise aiohttp.web.HTTPConflict(text="Appliance ID {} cannot be duplicated because it is a builtin".format(appliance_id))
appliance_settings = copy.deepcopy(appliance.settings)
del appliance_settings["appliance_id"]
return self.add_appliance(appliance_settings)
def load_appliances(self): def load_appliances(self):
#self._appliances = {} #self._appliances = {}

@ -115,7 +115,7 @@ class ApplianceHandler:
@Route.delete( @Route.delete(
r"/appliances/{appliance_id}", r"/appliances/{appliance_id}",
parameters={ parameters={
"appliance_id": "Node UUID" "appliance_id": "appliance UUID"
}, },
status_codes={ status_codes={
204: "Appliance deleted", 204: "Appliance deleted",
@ -140,6 +140,25 @@ class ApplianceHandler:
controller = Controller.instance() controller = Controller.instance()
response.json([c for c in controller.appliances.values()]) response.json([c for c in controller.appliances.values()])
@Route.post(
r"/appliances/{appliance_id}/duplicate",
parameters={
"appliance_id": "Appliance UUID"
},
status_codes={
201: "Appliance duplicated",
400: "Invalid request",
404: "Appliance doesn't exist"
},
description="Duplicate an appliance",
output=APPLIANCE_OBJECT_SCHEMA)
async def duplicate(request, response):
controller = Controller.instance()
appliance = controller.duplicate_appliance(request.match_info["appliance_id"])
response.set_status(201)
response.json(appliance)
@Route.post( @Route.post(
r"/projects/{project_id}/appliances/{appliance_id}", r"/projects/{project_id}/appliances/{appliance_id}",
description="Create a node from an appliance", description="Create a node from an appliance",

@ -210,6 +210,35 @@ def test_appliance_delete(http_controller, controller):
assert len(controller.appliances) == 0 assert len(controller.appliances) == 0
def test_appliance_duplicate(http_controller, controller):
appliance_id = str(uuid.uuid4())
params = {"appliance_id": appliance_id,
"base_script_file": "vpcs_base_config.txt",
"category": "guest",
"console_auto_start": False,
"console_type": "telnet",
"default_name_format": "PC{0}",
"name": "VPCS_TEST",
"compute_id": "local",
"symbol": ":/symbols/vpcs_guest.svg",
"appliance_type": "vpcs"}
response = http_controller.post("/appliances", params)
assert response.status == 201
response = http_controller.post("/appliances/{}/duplicate".format(appliance_id), example=True)
assert response.status == 201
assert response.json["appliance_id"] != appliance_id
params.pop("appliance_id")
for param, value in params.items():
assert response.json[param] == value
response = http_controller.get("/appliances")
assert len(response.json) == 2
assert len(controller.appliances) == 2
def test_c7200_dynamips_appliance_create(http_controller): def test_c7200_dynamips_appliance_create(http_controller):
params = {"name": "Cisco c7200 appliance", params = {"name": "Cisco c7200 appliance",

Loading…
Cancel
Save