diff --git a/gns3server/handlers/iou_handler.py b/gns3server/handlers/iou_handler.py index dc94e550..d54b762c 100644 --- a/gns3server/handlers/iou_handler.py +++ b/gns3server/handlers/iou_handler.py @@ -55,7 +55,8 @@ class IOUHandler: serial_adapters=request.json.get("serial_adapters"), ethernet_adapters=request.json.get("ethernet_adapters"), ram=request.json.get("ram"), - nvram=request.json.get("nvram") + nvram=request.json.get("nvram"), + l1_keepalives=request.json.get("l1_keepalives") ) vm.path = request.json.get("path", vm.path) vm.iourc_path = request.json.get("iourc_path", vm.iourc_path) @@ -110,6 +111,7 @@ class IOUHandler: vm.serial_adapters = request.json.get("serial_adapters", vm.serial_adapters) vm.ram = request.json.get("ram", vm.ram) vm.nvram = request.json.get("nvram", vm.nvram) + vm.l1_keepalives = request.json.get("l1_keepalives", vm.l1_keepalives) response.json(vm) diff --git a/gns3server/modules/iou/iou_vm.py b/gns3server/modules/iou/iou_vm.py index d2387c7d..d0fb4f60 100644 --- a/gns3server/modules/iou/iou_vm.py +++ b/gns3server/modules/iou/iou_vm.py @@ -61,6 +61,7 @@ class IOUVM(BaseVM): :params serial_adapters: Number of serial adapters :params ram: Ram MB :params nvram: Nvram KB + :params l1_keepalives: Always up ethernet interface """ def __init__(self, name, vm_id, project, manager, @@ -69,7 +70,8 @@ class IOUVM(BaseVM): ram=None, nvram=None, ethernet_adapters=None, - serial_adapters=None): + serial_adapters=None, + l1_keepalives=None): super().__init__(name, vm_id, project, manager) @@ -93,7 +95,7 @@ class IOUVM(BaseVM): self._nvram = 128 if nvram is None else nvram # Kilobytes self._initial_config = "" self._ram = 256 if ram is None else ram # Megabytes - self._l1_keepalives = False # used to overcome the always-up Ethernet interfaces (not supported by all IOSes). + self._l1_keepalives = False if l1_keepalives is None else l1_keepalives # used to overcome the always-up Ethernet interfaces (not supported by all IOSes). if self._console is not None: self._console = self._manager.port_manager.reserve_console_port(self._console) @@ -208,7 +210,8 @@ class IOUVM(BaseVM): "ethernet_adapters": len(self._ethernet_adapters), "serial_adapters": len(self._serial_adapters), "ram": self._ram, - "nvram": self._nvram + "nvram": self._nvram, + "l1_keepalives": self._l1_keepalives } @property @@ -759,3 +762,42 @@ class IOUVM(BaseVM): os.kill(self._iouyap_process.pid, signal.SIGHUP) return nio + + @property + def l1_keepalives(self): + """ + Returns either layer 1 keepalive messages option is enabled or disabled. + :returns: boolean + """ + + return self._l1_keepalives + + @l1_keepalives.setter + def l1_keepalives(self, state): + """ + Enables or disables layer 1 keepalive messages. + :param state: boolean + """ + + self._l1_keepalives = state + if state: + log.info("IOU {name} [id={id}]: has activated layer 1 keepalive messages".format(name=self._name, id=self._id)) + else: + log.info("IOU {name} [id={id}]: has deactivated layer 1 keepalive messages".format(name=self._name, id=self._id)) + + def _enable_l1_keepalives(self, command): + """ + Enables L1 keepalive messages if supported. + :param command: command line + """ + + env = os.environ.copy() + env["IOURC"] = self._iourc + try: + output = subprocess.check_output([self._path, "-h"], stderr=subprocess.STDOUT, cwd=self._working_dir, env=env) + if re.search("-l\s+Enable Layer 1 keepalive messages", output.decode("utf-8")): + command.extend(["-l"]) + else: + raise IOUError("layer 1 keepalive messages are not supported by {}".format(os.path.basename(self._path))) + except (OSError, subprocess.SubprocessError) as e: + log.warn("could not determine if layer 1 keepalive messages are supported by {}: {}".format(os.path.basename(self._path), e)) diff --git a/gns3server/modules/nios/nio_generic_ethernet.py b/gns3server/modules/nios/nio_generic_ethernet.py index 16b46e05..98dc91ca 100644 --- a/gns3server/modules/nios/nio_generic_ethernet.py +++ b/gns3server/modules/nios/nio_generic_ethernet.py @@ -23,6 +23,7 @@ from .nio import NIO class NIO_GenericEthernet(NIO): + """ Generic Ethernet NIO. diff --git a/gns3server/schemas/iou.py b/gns3server/schemas/iou.py index 6d304a19..0f578cf0 100644 --- a/gns3server/schemas/iou.py +++ b/gns3server/schemas/iou.py @@ -65,6 +65,10 @@ IOU_CREATE_SCHEMA = { "nvram": { "description": "Allocated NVRAM KB", "type": ["integer", "null"] + }, + "l1_keepalives": { + "description": "Always up ethernet interface", + "type": ["boolean", "null"] } }, "additionalProperties": False, @@ -114,6 +118,10 @@ IOU_UPDATE_SCHEMA = { "nvram": { "description": "Allocated NVRAM KB", "type": ["integer", "null"] + }, + "l1_keepalives": { + "description": "Always up ethernet interface", + "type": ["boolean", "null"] } }, "additionalProperties": False, @@ -168,10 +176,14 @@ IOU_OBJECT_SCHEMA = { "nvram": { "description": "Allocated NVRAM KB", "type": "integer" + }, + "l1_keepalives": { + "description": "Always up ethernet interface", + "type": "boolean" } }, "additionalProperties": False, - "required": ["name", "vm_id", "console", "project_id", "path", "serial_adapters", "ethernet_adapters", "ram", "nvram"] + "required": ["name", "vm_id", "console", "project_id", "path", "serial_adapters", "ethernet_adapters", "ram", "nvram", "l1_keepalives"] } IOU_NIO_SCHEMA = { diff --git a/tests/api/test_iou.py b/tests/api/test_iou.py index 3f5b40cb..09a7155c 100644 --- a/tests/api/test_iou.py +++ b/tests/api/test_iou.py @@ -56,6 +56,7 @@ def test_iou_create(server, project, base_params): assert response.json["ethernet_adapters"] == 2 assert response.json["ram"] == 256 assert response.json["nvram"] == 128 + assert response.json["l1_keepalives"] == False def test_iou_create_with_params(server, project, base_params): @@ -64,6 +65,7 @@ def test_iou_create_with_params(server, project, base_params): params["nvram"] = 512 params["serial_adapters"] = 4 params["ethernet_adapters"] = 0 + params["l1_keepalives"] = True response = server.post("/projects/{project_id}/iou/vms".format(project_id=project.id), params, example=True) assert response.status == 201 @@ -74,6 +76,7 @@ def test_iou_create_with_params(server, project, base_params): assert response.json["ethernet_adapters"] == 0 assert response.json["ram"] == 1024 assert response.json["nvram"] == 512 + assert response.json["l1_keepalives"] == True def test_iou_get(server, project, vm): @@ -86,6 +89,7 @@ def test_iou_get(server, project, vm): assert response.json["ethernet_adapters"] == 2 assert response.json["ram"] == 256 assert response.json["nvram"] == 128 + assert response.json["l1_keepalives"] == False def test_iou_start(server, vm): @@ -123,7 +127,8 @@ def test_iou_update(server, vm, tmpdir, free_console_port): "ram": 512, "nvram": 2048, "ethernet_adapters": 4, - "serial_adapters": 0 + "serial_adapters": 0, + "l1_keepalives": True } response = server.put("/projects/{project_id}/iou/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), params) assert response.status == 200 @@ -133,6 +138,7 @@ def test_iou_update(server, vm, tmpdir, free_console_port): assert response.json["serial_adapters"] == 0 assert response.json["ram"] == 512 assert response.json["nvram"] == 2048 + assert response.json["l1_keepalives"] == True def test_iou_nio_create_udp(server, vm):