diff --git a/gns3server/modules/dynamips/backends/vm.py b/gns3server/modules/dynamips/backends/vm.py index f0834809..e43767c9 100644 --- a/gns3server/modules/dynamips/backends/vm.py +++ b/gns3server/modules/dynamips/backends/vm.py @@ -73,8 +73,8 @@ import logging log = logging.getLogger(__name__) -ADAPTER_MATRIX = {"C7200_IO_2FE": C7200_IO_2FE, - "C7200_IO_FE": C7200_IO_FE, +ADAPTER_MATRIX = {"C7200-IO-2FE": C7200_IO_2FE, + "C7200-IO-FE": C7200_IO_FE, "C7200-IO-GE-E": C7200_IO_GE_E, "NM-16ESW": NM_16ESW, "NM-1E": NM_1E, @@ -468,7 +468,7 @@ class VM(object): except DynamipsError as e: self.send_custom_error(str(e)) return - elif name.startswith("slot") and value == None: + elif name.startswith("slot") and value is None: slot_id = int(name[-1]) if router.slots[slot_id]: try: diff --git a/gns3server/modules/dynamips/hypervisor.py b/gns3server/modules/dynamips/hypervisor.py index 20e49741..ac9af618 100644 --- a/gns3server/modules/dynamips/hypervisor.py +++ b/gns3server/modules/dynamips/hypervisor.py @@ -212,7 +212,7 @@ class Hypervisor(DynamipsHypervisor): cwd=self._working_dir) log.info("Dynamips started PID={}".format(self._process.pid)) self._started = True - except OSError as e: + except subprocess.SubprocessError as e: log.error("could not start Dynamips: {}".format(e)) raise DynamipsError("could not start Dynamips: {}".format(e)) diff --git a/gns3server/modules/dynamips/nodes/c7200.py b/gns3server/modules/dynamips/nodes/c7200.py index 0dd7127b..a473f954 100644 --- a/gns3server/modules/dynamips/nodes/c7200.py +++ b/gns3server/modules/dynamips/nodes/c7200.py @@ -22,7 +22,7 @@ http://github.com/GNS3/dynamips/blob/master/README.hypervisor#L294 from ..dynamips_error import DynamipsError from .router import Router -from ..adapters.c7200_io_2fe import C7200_IO_2FE +from ..adapters.c7200_io_fe import C7200_IO_FE from ..adapters.c7200_io_ge_e import C7200_IO_GE_E import logging @@ -70,7 +70,7 @@ class C7200(Router): if npe == "npe-g2": self.slot_add_binding(0, C7200_IO_GE_E()) else: - self.slot_add_binding(0, C7200_IO_2FE()) + self.slot_add_binding(0, C7200_IO_FE()) def defaults(self): """ diff --git a/gns3server/modules/dynamips/nodes/router.py b/gns3server/modules/dynamips/nodes/router.py index ea32ac12..eb665d7f 100644 --- a/gns3server/modules/dynamips/nodes/router.py +++ b/gns3server/modules/dynamips/nodes/router.py @@ -1324,7 +1324,7 @@ class Router(object): adapter=current_adapter)) # Only c7200, c3600 and c3745 (NM-4T only) support new adapter while running - if self.is_running() and not (self._platform == 'c7200' + if self.is_running() and not ((self._platform == 'c7200' and not str(adapter).startswith('C7200')) and not (self._platform == 'c3600' and self.chassis == '3660') and not (self._platform == 'c3745' and adapter == 'NM-4T')): raise DynamipsError("Adapter {adapter} cannot be added while router {name} is running".format(adapter=adapter, @@ -1369,7 +1369,7 @@ class Router(object): slot_id=slot_id)) # Only c7200, c3600 and c3745 (NM-4T only) support to remove adapter while running - if self.is_running() and not (self._platform == 'c7200' + if self.is_running() and not ((self._platform == 'c7200' and not str(adapter).startswith('C7200')) and not (self._platform == 'c3600' and self.chassis == '3660') and not (self._platform == 'c3745' and adapter == 'NM-4T')): raise DynamipsError("Adapter {adapter} cannot be removed while router {name} is running".format(adapter=adapter, diff --git a/gns3server/modules/iou/iou_device.py b/gns3server/modules/iou/iou_device.py index d12a7b45..0988f226 100644 --- a/gns3server/modules/iou/iou_device.py +++ b/gns3server/modules/iou/iou_device.py @@ -509,7 +509,7 @@ class IOUDevice(object): cwd=self._working_dir) log.info("iouyap started PID={}".format(self._iouyap_process.pid)) - except OSError as e: + except subprocess.SubprocessError as e: iouyap_stdout = self.read_iouyap_stdout() log.error("could not start iouyap: {}\n{}".format(e, iouyap_stdout)) raise IOUError("Could not start iouyap: {}\n{}".format(e, iouyap_stdout)) @@ -521,7 +521,7 @@ class IOUDevice(object): try: output = subprocess.check_output(["ldd", self._path]) - except (FileNotFoundError, subprocess.CalledProcessError) as e: + except (FileNotFoundError, subprocess.SubprocessError) as e: log.warn("could not determine the shared library dependencies for {}: {}".format(self._path, e)) return @@ -583,7 +583,7 @@ class IOUDevice(object): self._started = True except FileNotFoundError as e: raise IOUError("could not start IOU: {}: 32-bit binary support is probably not installed".format(e)) - except OSError as e: + except subprocess.SubprocessError as e: iou_stdout = self.read_iou_stdout() log.error("could not start IOU {}: {}\n{}".format(self._path, e, iou_stdout)) raise IOUError("could not start IOU {}: {}\n{}".format(self._path, e, iou_stdout)) @@ -761,7 +761,7 @@ class IOUDevice(object): command.extend(["-l"]) else: raise IOUError("layer 1 keepalive messages are not supported by {}".format(os.path.basename(self._path))) - except (OSError, subprocess.CalledProcessError) as e: + except subprocess.SubprocessError as e: log.warn("could not determine if layer 1 keepalive messages are supported by {}: {}".format(os.path.basename(self._path), e)) def _build_command(self): diff --git a/gns3server/modules/qemu/__init__.py b/gns3server/modules/qemu/__init__.py index 37998cdc..4816dfc8 100644 --- a/gns3server/modules/qemu/__init__.py +++ b/gns3server/modules/qemu/__init__.py @@ -601,14 +601,14 @@ class Qemu(IModule): if sys.platform.startswith("win"): return "" try: - output = subprocess.check_output([qemu_path, "--version"]) - match = re.search("QEMU emulator version ([0-9a-z\-\.]+)", output.decode("utf-8")) + output = subprocess.check_output([qemu_path, "-version"]) + match = re.search("version\s+([0-9a-z\-\.]+)", output.decode("utf-8")) if match: version = match.group(1) return version else: raise QemuError("Could not determine the Qemu version for {}".format(qemu_path)) - except (OSError, subprocess.CalledProcessError) as e: + except subprocess.SubprocessError as e: raise QemuError("Error while looking for the Qemu version: {}".format(e)) @IModule.route("qemu.qemu_list") @@ -625,7 +625,13 @@ class Qemu(IModule): # look for Qemu binaries in the current working directory and $PATH if sys.platform.startswith("win"): # add specific Windows paths - paths.append(os.path.join(os.getcwd(), "qemu")) + if hasattr(sys, "frozen"): + # add any qemu dir in the same location as gns3server.exe to the list of paths + exec_dir = os.path.dirname(os.path.abspath(sys.executable)) + for f in os.listdir(exec_dir): + if f.lower().startswith("qemu"): + paths.append(os.path.join(exec_dir, f)) + if "PROGRAMFILES(X86)" in os.environ and os.path.exists(os.environ["PROGRAMFILES(X86)"]): paths.append(os.path.join(os.environ["PROGRAMFILES(X86)"], "qemu")) if "PROGRAMFILES" in os.environ and os.path.exists(os.environ["PROGRAMFILES"]): @@ -633,15 +639,18 @@ class Qemu(IModule): elif sys.platform.startswith("darwin"): # add specific locations on Mac OS X regardless of what's in $PATH paths.extend(["/usr/local/bin", "/opt/local/bin"]) + if hasattr(sys, "frozen"): + paths.append(os.path.abspath(os.path.join(os.getcwd(), "../../../qemu/bin/"))) for path in paths: try: for f in os.listdir(path): - if (f.startswith("qemu-system") or f == "qemu" or f == "qemu.exe") and os.access(os.path.join(path, f), os.X_OK): + if (f.startswith("qemu-system") or f == "qemu" or f == "qemu.exe") and \ + os.access(os.path.join(path, f), os.X_OK) and \ + os.path.isfile(os.path.join(path, f)): qemu_path = os.path.join(path, f) version = self._get_qemu_version(qemu_path) qemus.append({"path": qemu_path, "version": version}) - except (OSError, QemuError) as e: - log.warn("Could not find QEMU version for {}: {}".format(path, e)) + except OSError: continue response = {"qemus": qemus} diff --git a/gns3server/modules/qemu/qemu_vm.py b/gns3server/modules/qemu/qemu_vm.py index ce1242c8..57a5b42d 100644 --- a/gns3server/modules/qemu/qemu_vm.py +++ b/gns3server/modules/qemu/qemu_vm.py @@ -19,6 +19,7 @@ QEMU VM instance. """ +import sys import os import shutil import random @@ -89,6 +90,7 @@ class QemuVM(object): self._command = [] self._started = False self._process = None + self._cpulimit_process = None self._stdout_file = "" self._console_host = console_host self._console_start_port_range = console_start_port_range @@ -107,6 +109,9 @@ class QemuVM(object): self._initrd = "" self._kernel_image = "" self._kernel_command_line = "" + self._legacy_networking = False + self._cpu_throttling = 0 # means no CPU throttling + self._process_priority = "low" working_dir_path = os.path.join(working_dir, "qemu", "vm-{}".format(self._id)) @@ -152,7 +157,11 @@ class QemuVM(object): "console": self._console, "initrd": self._initrd, "kernel_image": self._kernel_image, - "kernel_command_line": self._kernel_command_line} + "kernel_command_line": self._kernel_command_line, + "legacy_networking": self._legacy_networking, + "cpu_throttling": self._cpu_throttling, + "process_priority": self._process_priority + } return qemu_defaults @@ -437,6 +446,80 @@ class QemuVM(object): id=self._id, adapter_type=adapter_type)) + @property + def legacy_networking(self): + """ + Returns either QEMU legacy networking commands are used. + + :returns: boolean + """ + + return self._legacy_networking + + @legacy_networking.setter + def legacy_networking(self, legacy_networking): + """ + Sets either QEMU legacy networking commands are used. + + :param legacy_networking: boolean + """ + + if legacy_networking: + log.info("QEMU VM {name} [id={id}] has enabled legacy networking".format(name=self._name, id=self._id)) + else: + log.info("QEMU VM {name} [id={id}] has disabled legacy networking".format(name=self._name, id=self._id)) + self._legacy_networking = legacy_networking + + @property + def cpu_throttling(self): + """ + Returns the percentage of CPU allowed. + + :returns: integer + """ + + return self._cpu_throttling + + @cpu_throttling.setter + def cpu_throttling(self, cpu_throttling): + """ + Sets the percentage of CPU allowed. + + :param cpu_throttling: integer + """ + + log.info("QEMU VM {name} [id={id}] has set the percentage of CPU allowed to {cpu}".format(name=self._name, + id=self._id, + cpu=cpu_throttling)) + self._cpu_throttling = cpu_throttling + self._stop_cpulimit() + if cpu_throttling: + self._set_cpu_throttling() + + @property + def process_priority(self): + """ + Returns the process priority. + + :returns: string + """ + + return self._process_priority + + @process_priority.setter + def process_priority(self, process_priority): + """ + Sets the process priority. + + :param process_priority: string + """ + + log.info("QEMU VM {name} [id={id}] has set the process priority to {priority}".format(name=self._name, + id=self._id, + priority=process_priority)) + self._process_priority = process_priority + + @property def ram(self): """ @@ -552,6 +635,84 @@ class QemuVM(object): kernel_command_line=kernel_command_line)) self._kernel_command_line = kernel_command_line + def _set_process_priority(self): + """ + Changes the process priority + """ + + if sys.platform.startswith("win"): + try: + import win32api + import win32con + import win32process + except ImportError: + log.error("pywin32 must be installed to change the priority class for QEMU VM {}".format(self._name)) + else: + log.info("setting QEMU VM {} priority class to BELOW_NORMAL".format(self._name)) + handle = win32api.OpenProcess(win32con.PROCESS_ALL_ACCESS, 0, self._process.pid) + if self._process_priority == "realtime": + priority = win32process.REALTIME_PRIORITY_CLASS + elif self._process_priority == "very high": + priority = win32process.HIGH_PRIORITY_CLASS + elif self._process_priority == "high": + priority = win32process.ABOVE_NORMAL_PRIORITY_CLASS + elif self._process_priority == "low": + priority = win32process.BELOW_NORMAL_PRIORITY_CLASS + elif self._process_priority == "very low": + priority = win32process.IDLE_PRIORITY_CLASS + else: + priority = win32process.NORMAL_PRIORITY_CLASS + win32process.SetPriorityClass(handle, priority) + else: + if self._process_priority == "realtime": + priority = -20 + elif self._process_priority == "very high": + priority = -15 + elif self._process_priority == "high": + priority = -5 + elif self._process_priority == "low": + priority = 5 + elif self._process_priority == "very low": + priority = 19 + else: + priority = 0 + try: + subprocess.call(['renice', '-n', str(priority), '-p', str(self._process.pid)]) + except subprocess.SubprocessError as e: + log.error("could not change process priority for QEMU VM {}: {}".format(self._name, e)) + + def _stop_cpulimit(self): + """ + Stops the cpulimit process. + """ + + if self._cpulimit_process and self._cpulimit_process.poll() is None: + self._cpulimit_process.kill() + try: + self._process.wait(3) + except subprocess.TimeoutExpired: + log.error("could not kill cpulimit process {}".format(self._cpulimit_process.pid)) + + def _set_cpu_throttling(self): + """ + Limits the CPU usage for current QEMU process. + """ + + if not self.is_running(): + return + + try: + if sys.platform.startswith("win") and hasattr(sys, "frozen"): + cpulimit_exec = os.path.join(os.path.dirname(os.path.abspath(sys.executable)), "cpulimit", "cpulimit.exe") + else: + cpulimit_exec = "cpulimit" + subprocess.Popen([cpulimit_exec, "--lazy", "--pid={}".format(self._process.pid), "--limit={}".format(self._cpu_throttling)], cwd=self._working_dir) + log.info("CPU throttled to {}%".format(self._cpu_throttling)) + except FileNotFoundError: + raise QemuError("cpulimit could not be found, please install it or deactivate CPU throttling") + except subprocess.SubprocessError as e: + raise QemuError("Could not throttle CPU: {}".format(e)) + def start(self): """ Starts this QEMU VM. @@ -612,11 +773,15 @@ class QemuVM(object): cwd=self._working_dir) log.info("QEMU VM instance {} started PID={}".format(self._id, self._process.pid)) self._started = True - except OSError as e: + except subprocess.SubprocessError as e: stdout = self.read_stdout() log.error("could not start QEMU {}: {}\n{}".format(self._qemu_path, e, stdout)) raise QemuError("could not start QEMU {}: {}\n{}".format(self._qemu_path, e, stdout)) + self._set_process_priority() + if self._cpu_throttling: + self._set_cpu_throttling() + def stop(self): """ Stops this QEMU VM. @@ -635,6 +800,7 @@ class QemuVM(object): self._process.pid)) self._process = None self._started = False + self._stop_cpulimit() def suspend(self): """ @@ -782,7 +948,7 @@ class QemuVM(object): retcode = subprocess.call([qemu_img_path, "create", "-f", "qcow2", hda_disk, "128M"]) log.info("{} returned with {}".format(qemu_img_path, retcode)) - except OSError as e: + except subprocess.SubprocessError as e: raise QemuError("Could not create disk image {}".format(e)) options.extend(["-hda", hda_disk]) @@ -794,7 +960,7 @@ class QemuVM(object): "backing_file={}".format(self._hdb_disk_image), "-f", "qcow2", hdb_disk]) log.info("{} returned with {}".format(qemu_img_path, retcode)) - except OSError as e: + except subprocess.SubprocessError as e: raise QemuError("Could not create disk image {}".format(e)) options.extend(["-hdb", hdb_disk]) @@ -819,16 +985,29 @@ class QemuVM(object): for adapter in self._ethernet_adapters: #TODO: let users specify a base mac address mac = "00:00:ab:%02x:%02x:%02d" % (random.randint(0x00, 0xff), random.randint(0x00, 0xff), adapter_id) - network_options.extend(["-device", "{},mac={},netdev=gns3-{}".format(self._adapter_type, mac, adapter_id)]) + if self._legacy_networking: + network_options.extend(["-net", "nic,vlan={},macaddr={},model={}".format(adapter_id, mac, self._adapter_type)]) + else: + network_options.extend(["-device", "{},mac={},netdev=gns3-{}".format(self._adapter_type, mac, adapter_id)]) nio = adapter.get_nio(0) if nio and isinstance(nio, NIO_UDP): - network_options.extend(["-netdev", "socket,id=gns3-{},udp={}:{},localaddr={}:{}".format(adapter_id, - nio.rhost, - nio.rport, - self._host, - nio.lport)]) + if self._legacy_networking: + network_options.extend(["-net", "udp,vlan={},sport={},dport={},daddr={}".format(adapter_id, + nio.lport, + nio.rport, + nio.rhost)]) + + else: + network_options.extend(["-netdev", "socket,id=gns3-{},udp={}:{},localaddr={}:{}".format(adapter_id, + nio.rhost, + nio.rport, + self._host, + nio.lport)]) else: - network_options.extend(["-netdev", "user,id=gns3-{}".format(adapter_id)]) + if self._legacy_networking: + network_options.extend(["-net", "user,vlan={}".format(adapter_id)]) + else: + network_options.extend(["-netdev", "user,id=gns3-{}".format(adapter_id)]) adapter_id += 1 return network_options diff --git a/gns3server/modules/qemu/schemas.py b/gns3server/modules/qemu/schemas.py index adc766f8..5807d2a7 100644 --- a/gns3server/modules/qemu/schemas.py +++ b/gns3server/modules/qemu/schemas.py @@ -124,8 +124,27 @@ QEMU_UPDATE_SCHEMA = { "description": "Path to the image in the cloud object store", "type": "string", }, + "legacy_networking": { + "description": "Use QEMU legagy networking commands (-net syntax)", + "type": "boolean", + }, + "cpu_throttling": { + "description": "Percentage of CPU allowed for QEMU", + "minimum": 0, + "maximum": 800, + "type": "integer", + }, + "process_priority": { + "description": "Process priority for QEMU", + "enum": ["realtime", + "very high", + "high", + "normal", + "low", + "very low"] + }, "options": { - "description": "additional QEMU options", + "description": "Additional QEMU options", "type": "string", }, }, diff --git a/gns3server/modules/virtualbox/__init__.py b/gns3server/modules/virtualbox/__init__.py index 649b4022..4a3fb40f 100644 --- a/gns3server/modules/virtualbox/__init__.py +++ b/gns3server/modules/virtualbox/__init__.py @@ -62,8 +62,13 @@ class VirtualBox(IModule): # get the vboxmanage location self._vboxmanage_path = None - if sys.platform.startswith("win") and "VBOX_INSTALL_PATH" in os.environ: - self._vboxmanage_path = os.path.join(os.environ["VBOX_INSTALL_PATH"], "VBoxManage.exe") + if sys.platform.startswith("win"): + if "VBOX_INSTALL_PATH" in os.environ: + self._vboxmanage_path = os.path.join(os.environ["VBOX_INSTALL_PATH"], "VBoxManage.exe") + elif "VBOX_MSI_INSTALL_PATH" in os.environ: + self._vboxmanage_path = os.path.join(os.environ["VBOX_MSI_INSTALL_PATH"], "VBoxManage.exe") + elif sys.platform.startswith("darwin"): + self._vboxmanage_path = "/Applications/VirtualBox.app/Contents/MacOS/VBoxManage" else: config = Config.instance() vbox_config = config.get_section_config(name.upper()) @@ -716,12 +721,10 @@ class VirtualBox(IModule): """ try: - result = subprocess.check_output(command, stderr=subprocess.STDOUT, universal_newlines=True, timeout=30) - except subprocess.CalledProcessError as e: + result = subprocess.check_output(command, stderr=subprocess.STDOUT, timeout=30) + except subprocess.SubprocessError as e: raise VirtualBoxError("Could not execute VBoxManage {}".format(e)) - except subprocess.TimeoutExpired: - raise VirtualBoxError("VBoxManage has timed out") - return result + return result.decode("utf-8") @IModule.route("virtualbox.vm_list") def vm_list(self, request): @@ -753,7 +756,13 @@ class VirtualBox(IModule): for line in result.splitlines(): vmname, uuid = line.rsplit(' ', 1) vmname = vmname.strip('"') - extra_data = self._execute_vboxmanage([vboxmanage_path, "getextradata", vmname, "GNS3/Clone"]).strip() + if vmname == "": + continue # ignore inaccessible VMs + try: + extra_data = self._execute_vboxmanage([vboxmanage_path, "getextradata", vmname, "GNS3/Clone"]).strip() + except VirtualBoxError as e: + self.send_custom_error(str(e)) + return if not extra_data == "Value: yes": vms.append(vmname) diff --git a/gns3server/modules/virtualbox/virtualbox_vm.py b/gns3server/modules/virtualbox/virtualbox_vm.py index 1a3597c1..cf1dc3a6 100644 --- a/gns3server/modules/virtualbox/virtualbox_vm.py +++ b/gns3server/modules/virtualbox/virtualbox_vm.py @@ -322,8 +322,8 @@ class VirtualBoxVM(object): self._allocated_console_ports.remove(self.console) if self._linked_clone: + hdd_table = [] if os.path.exists(self._working_dir): - hdd_table = [] hdd_files = self._get_all_hdd_files() vm_info = self._get_vm_info() for entry, value in vm_info.items(): @@ -550,17 +550,17 @@ class VirtualBoxVM(object): command.extend(args) log.debug("Execute vboxmanage command: {}".format(command)) try: - result = subprocess.check_output(command, stderr=subprocess.STDOUT, universal_newlines=True, timeout=timeout) + result = subprocess.check_output(command, stderr=subprocess.STDOUT, timeout=timeout) except subprocess.CalledProcessError as e: if e.output: # only the first line of the output is useful - virtualbox_error = e.output.splitlines()[0] + virtualbox_error = e.output.decode("utf-8").splitlines()[0] raise VirtualBoxError("{}".format(virtualbox_error)) else: raise VirtualBoxError("{}".format(e)) - except subprocess.TimeoutExpired: - raise VirtualBoxError("VBoxManage has timed out") - return result.splitlines() + except subprocess.SubprocessError as e: + raise VirtualBoxError("Could not execute VBoxManage: {}".format(e)) + return result.decode("utf-8").splitlines() def _get_vm_info(self): """ diff --git a/gns3server/modules/vpcs/vpcs_device.py b/gns3server/modules/vpcs/vpcs_device.py index cd89b00e..377e9bf0 100644 --- a/gns3server/modules/vpcs/vpcs_device.py +++ b/gns3server/modules/vpcs/vpcs_device.py @@ -346,7 +346,7 @@ class VPCSDevice(object): raise VPCSError("VPCS executable version must be >= 0.5b1") else: raise VPCSError("Could not determine the VPCS version for {}".format(self._path)) - except (OSError, subprocess.CalledProcessError) as e: + except subprocess.SubprocessError as e: raise VPCSError("Error while looking for the VPCS version: {}".format(e)) def start(self): @@ -386,7 +386,7 @@ class VPCSDevice(object): creationflags=flags) log.info("VPCS instance {} started PID={}".format(self._id, self._process.pid)) self._started = True - except OSError as e: + except subprocess.SubprocessError as e: vpcs_stdout = self.read_vpcs_stdout() log.error("could not start VPCS {}: {}\n{}".format(self._path, e, vpcs_stdout)) raise VPCSError("could not start VPCS {}: {}\n{}".format(self._path, e, vpcs_stdout)) diff --git a/gns3server/server.py b/gns3server/server.py index e178c9f9..5d748dc2 100644 --- a/gns3server/server.py +++ b/gns3server/server.py @@ -184,7 +184,6 @@ class Server(object): except KeyError: log.info("Missing cloud.conf - disabling HTTP auth and SSL") - router = self._create_zmq_router() # Add our JSON-RPC Websocket handler to Tornado self.handlers.extend([(r"/", JSONRPCWebSocket, dict(zmq_router=router))]) @@ -208,6 +207,7 @@ class Server(object): if parse_version(tornado.version) >= parse_version("3.1"): kwargs["max_buffer_size"] = 524288000 # 500 MB file upload limit + tornado_app.listen(self._port, **kwargs) except OSError as e: if e.errno == errno.EADDRINUSE: # socket already in use diff --git a/gns3server/version.py b/gns3server/version.py index 579a7caa..aad30941 100644 --- a/gns3server/version.py +++ b/gns3server/version.py @@ -23,5 +23,5 @@ # or negative for a release candidate or beta (after the base version # number has been incremented) -__version__ = "1.2.dev3" -__version_info__ = (1, 2, 0, 99) +__version__ = "1.2.2.dev1" +__version_info__ = (1, 2, 2, 0) diff --git a/scripts/ws_client.py b/scripts/ws_client.py new file mode 100644 index 00000000..675bc7c3 --- /dev/null +++ b/scripts/ws_client.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2014 GNS3 Technologies Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from ws4py.client.threadedclient import WebSocketClient + + +class WSClient(WebSocketClient): + + def opened(self): + + print("Connection successful with {}:{}".format(self.host, self.port)) + + self.send('{"jsonrpc": 2.0, "method": "dynamips.settings", "params": {"path": "/usr/local/bin/dynamips", "allocate_hypervisor_per_device": true, "working_dir": "/tmp/gns3-1b4grwm3-files", "udp_end_port_range": 20000, "sparse_memory_support": true, "allocate_hypervisor_per_ios_image": true, "aux_start_port_range": 2501, "use_local_server": true, "hypervisor_end_port_range": 7700, "aux_end_port_range": 3000, "mmap_support": true, "console_start_port_range": 2001, "console_end_port_range": 2500, "hypervisor_start_port_range": 7200, "ghost_ios_support": true, "memory_usage_limit_per_hypervisor": 1024, "jit_sharing_support": false, "udp_start_port_range": 10001}}') + self.send('{"jsonrpc": 2.0, "method": "dynamips.vm.create", "id": "e8caf5be-de3d-40dd-80b9-ab6df8029570", "params": {"image": "/home/grossmj/GNS3/images/IOS/c3725-advipservicesk9-mz.124-15.T14.image", "name": "R1", "platform": "c3725", "ram": 256}}') + + def closed(self, code, reason=None): + + print("Closed down. Code: {} Reason: {}".format(code, reason)) + + def received_message(self, m): + + print(m) + if len(m) == 175: + self.close(reason='Bye bye') + +if __name__ == '__main__': + try: + ws = WSClient('ws://localhost:8000/', protocols=['http-only', 'chat']) + ws.connect() + ws.run_forever() + except KeyboardInterrupt: + ws.close() \ No newline at end of file