diff --git a/gns3server/compute/base_manager.py b/gns3server/compute/base_manager.py index 17a41fe7e..a3ee38cec 100644 --- a/gns3server/compute/base_manager.py +++ b/gns3server/compute/base_manager.py @@ -221,6 +221,9 @@ class BaseManager: if not hasattr(destination_node, "working_dir"): return destination_node + if hasattr(source_node, "status") and source_node.status != "stopped": + raise ComputeError("Cannot duplicate node data while the node is running") + destination_dir = destination_node.working_dir try: shutil.rmtree(destination_dir) diff --git a/gns3server/compute/dynamips/__init__.py b/gns3server/compute/dynamips/__init__.py index eae8ab61e..4362b9be1 100644 --- a/gns3server/compute/dynamips/__init__.py +++ b/gns3server/compute/dynamips/__init__.py @@ -478,36 +478,40 @@ class Dynamips(BaseManager): adapter = ADAPTER_MATRIX[adapter_name]() try: if vm.slots[slot_id] and not isinstance(vm.slots[slot_id], type(adapter)): - await vm.slot_remove_binding(slot_id) + if vm.slots[slot_id].removable(): + await vm.slot_remove_binding(slot_id) + else: + log.warning(f"Slot {slot_id} on router '{vm.name}' has a non-removable adapter, skipping replacement") + continue if not isinstance(vm.slots[slot_id], type(adapter)): await vm.slot_add_binding(slot_id, adapter) except IndexError: - raise DynamipsError(f"Slot {slot_id} doesn't exist on this router") + log.warning(f"Slot {slot_id} doesn't exist on router '{vm.name}', skipping") elif name.startswith("slot") and (value is None or value == ""): slot_id = int(name[-1]) try: - if vm.slots[slot_id]: + if vm.slots[slot_id] and vm.slots[slot_id].removable(): await vm.slot_remove_binding(slot_id) except IndexError: - raise DynamipsError(f"Slot {slot_id} doesn't exist on this router") + log.warning(f"Slot {slot_id} doesn't exist on router '{vm.name}', skipping") elif name.startswith("wic") and value in WIC_MATRIX: wic_slot_id = int(name[-1]) wic_name = value wic = WIC_MATRIX[wic_name]() try: - if vm.slots[0].wics[wic_slot_id] and not isinstance(vm.slots[0].wics[wic_slot_id], type(wic)): + if vm.slots[0] and vm.slots[0].wics[wic_slot_id] and not isinstance(vm.slots[0].wics[wic_slot_id], type(wic)): await vm.uninstall_wic(wic_slot_id) - if not isinstance(vm.slots[0].wics[wic_slot_id], type(wic)): + if vm.slots[0] and not isinstance(vm.slots[0].wics[wic_slot_id], type(wic)): await vm.install_wic(wic_slot_id, wic) - except IndexError: - raise DynamipsError(f"WIC slot {wic_slot_id} doesn't exist on this router") + except (IndexError, AttributeError): + log.warning(f"WIC slot {wic_slot_id} doesn't exist on router '{vm.name}', skipping") elif name.startswith("wic") and (value is None or value == ""): wic_slot_id = int(name[-1]) try: - if vm.slots[0].wics and vm.slots[0].wics[wic_slot_id]: + if vm.slots[0] and vm.slots[0].wics and vm.slots[0].wics[wic_slot_id]: await vm.uninstall_wic(wic_slot_id) - except IndexError: - raise DynamipsError(f"WIC slot {wic_slot_id} doesn't exist on this router") + except (IndexError, AttributeError): + log.warning(f"WIC slot {wic_slot_id} doesn't exist on router '{vm.name}', skipping") mmap_support = self.config.settings.Dynamips.mmap_support if mmap_support is False: diff --git a/gns3server/controller/node.py b/gns3server/controller/node.py index 37dcff665..ffd15a728 100644 --- a/gns3server/controller/node.py +++ b/gns3server/controller/node.py @@ -556,7 +556,7 @@ class Node: # None properties are not be sent because it can mean the emulator doesn't support it for key, value in list(data.items()): if value is None or value == {} or key in self.CONTROLLER_ONLY_PROPERTIES: - del value + del data[key] return data diff --git a/gns3server/controller/project.py b/gns3server/controller/project.py index e73602d54..98597649d 100644 --- a/gns3server/controller/project.py +++ b/gns3server/controller/project.py @@ -1280,9 +1280,6 @@ class Project: :returns: New node """ - if node.status != "stopped" and not node.is_always_running(): - raise ControllerError("Cannot duplicate node data while the node is running") - data = copy.deepcopy(node.asdict(topology_dump=True)) # Some properties like internal ID should not be duplicated for unique_property in (